hakyll-dhall 0.1.0.0 → 0.2.0.0
raw patch · 5 files changed
+242/−128 lines, 5 filesdep ~hakyllPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: hakyll
API changes (from Hackage documentation)
- Hakyll.Web.Dhall: dhallFullCompiler :: Compiler (Item String)
- Hakyll.Web.Dhall: dhallRawCompiler :: Compiler (Item String)
- Hakyll.Web.Dhall: loadDhallExpr :: DefaultDhallResolver a => Identifier -> Compiler (Item (Expr Src a))
- Hakyll.Web.Dhall: loadDhallExprWith :: DhallCompilerOptions a -> Identifier -> Compiler (Item (Expr Src a))
- Hakyll.Web.Dhall: loadDhallWith :: DhallCompilerOptions X -> Type a -> Identifier -> Compiler (Item a)
- Hakyll.Web.Dhall: parseRawDhallWith :: DhallCompilerOptions Import -> Maybe Identifier -> Text -> Compiler (Expr Src Import)
+ Hakyll.Web.Dhall: dExprCompiler :: DefaultDhallResolver a => Compiler (Item (DExpr a))
+ Hakyll.Web.Dhall: dExprCompilerWith :: DhallCompilerOptions a -> Compiler (Item (DExpr a))
+ Hakyll.Web.Dhall: dhallFullPrettyCompiler :: Compiler (Item String)
+ Hakyll.Web.Dhall: dhallPrettyCompiler :: forall a. (DefaultDhallResolver a, Pretty a) => Compiler (Item String)
+ Hakyll.Web.Dhall: dhallPrettyCompilerWith :: Pretty a => DhallCompilerOptions a -> Compiler (Item String)
+ Hakyll.Web.Dhall: dhallRawPrettyCompiler :: Compiler (Item String)
+ Hakyll.Web.Dhall: loadDhallSnapshot :: Type a -> Identifier -> Snapshot -> Compiler (Item a)
+ Hakyll.Web.Dhall: parseDhallExpr :: DefaultDhallResolver a => Maybe FilePath -> Text -> Compiler (Expr Src a)
+ Hakyll.Web.Dhall: parseDhallExprWith :: DhallCompilerOptions a -> Maybe FilePath -> Text -> Compiler (Expr Src a)
+ Hakyll.Web.Dhall: parseRawDhallExprWith :: DhallCompilerOptions Import -> Text -> Compiler (Expr Src Import)
- Hakyll.Web.Dhall: dhallCompiler :: forall a. (DefaultDhallResolver a, Pretty a) => Compiler (Item String)
+ Hakyll.Web.Dhall: dhallCompiler :: Type a -> Compiler (Item a)
- Hakyll.Web.Dhall: dhallCompilerWith :: Pretty a => DhallCompilerOptions a -> Compiler (Item String)
+ Hakyll.Web.Dhall: dhallCompilerWith :: DhallCompilerOptions X -> Type a -> Compiler (Item a)
- Hakyll.Web.Dhall: parseDhall :: DefaultDhallResolver a => Maybe Identifier -> Text -> Compiler (Expr Src a)
+ Hakyll.Web.Dhall: parseDhall :: Type a -> Maybe FilePath -> Text -> Compiler (Item a)
- Hakyll.Web.Dhall: parseDhallWith :: DhallCompilerOptions a -> Maybe Identifier -> Text -> Compiler (Expr Src a)
+ Hakyll.Web.Dhall: parseDhallWith :: DhallCompilerOptions X -> Type a -> Maybe FilePath -> Text -> Compiler (Item a)
- Hakyll.Web.Dhall: resolveDhallImports :: DhallCompilerOptions X -> Maybe Identifier -> Expr Src Import -> Compiler (Expr Src X)
+ Hakyll.Web.Dhall: resolveDhallImports :: DhallCompilerOptions X -> Maybe FilePath -> Expr Src Import -> Compiler (Expr Src X)
Files
- CHANGELOG.md +10/−1
- README.md +18/−0
- app/test-app.hs +2/−2
- hakyll-dhall.cabal +7/−8
- src/Hakyll/Web/Dhall.hs +205/−117
CHANGELOG.md view
@@ -1,10 +1,19 @@ Changelog ========= +Version 0.2.0.0+---------------++*October 8, 2018*++<https://github.com/mstksg/backprop/releases/tag/v0.2.0.0>++* Revamped workflow; largely incompatible with v0.1.0.0.+ Version 0.1.0.0 --------------- -*October 3, 2018*+*October 7, 2018* <https://github.com/mstksg/backprop/releases/tag/v0.1.0.0>
README.md view
@@ -16,6 +16,24 @@ `dhallCompiler` is meant as a "final end-point", which just pretty-prints a parsed Dhall file, with optional normalization. +Hakyll compiler and loader for Dhall files. Functions are intended to+track all local dependencies within the project directory, so rebuilds+are properly triggered on up-stream imports. Provides options for+customizing rebuilding behavior for network, environment variable, and+non-project local files.++There are three major workflows:++1. `dExprCompiler`, `loadDhall`, and `dhallCompiler`, for loading underlying+ Dhall files, saving them into the Hakyll cache and later interpreting them+ as values.++2. `parseDhall` and `parseDhallExpr`, for parsing Dhall expressions provided as+ strings, and resolving them while tracking dependencies.++3. `dhallPrettyCompiler`, for processing and re-formatting Dhall files and+ presenting them as-is as a "final end-point".+ [hakyll-dhall]: http://hackage.haskell.org/package/hakyll-dhall [hakyll]: http://hackage.haskell.org/package/hakyll [dhall]: http://hackage.haskell.org/package/dhall
app/test-app.hs view
@@ -8,8 +8,8 @@ main = hakyll $ do match "test-dhall/**" $ do route idRoute- compile dhallFullCompiler+ compile dhallFullPrettyCompiler create ["testparse.txt"] $ do route idRoute- compile $ loadDhall (auto :: Type String) "test-dhall/parse-test.dhall"+ compile $ parseDhall (auto :: Type String) Nothing "./test-dhall/parse-test.dhall"
hakyll-dhall.cabal view
@@ -1,13 +1,11 @@-cabal-version: 1.12---- This file has been generated from package.yaml by hpack version 0.30.0.+-- This file has been generated from package.yaml by hpack version 0.28.2. -- -- see: https://github.com/sol/hpack ----- hash: 25f480672df6d437301f7a05c8f3999bdc244d13ea7a789df755a6a6419a734c+-- hash: 09eb91e35254576dbe38981485e439fbef1d3cef1b8551e4bf7591c372261be9 name: hakyll-dhall-version: 0.1.0.0+version: 0.2.0.0 synopsis: Dhall compiler for Hakyll description: Please see the README on GitHub at <https://github.com/mstksg/hakyll-dhall#readme> category: Web@@ -20,9 +18,10 @@ license-file: LICENSE tested-with: GHC >= 8.2 && < 8.8 build-type: Simple+cabal-version: >= 1.10 extra-source-files:- README.md CHANGELOG.md+ README.md test-dhall/foo.dhall test-dhall/parse-test.dhall test-dhall/test-file.dhall@@ -49,7 +48,7 @@ , data-default-class , dhall >1.17 , filepath- , hakyll+ , hakyll >=4.10 , lens-family-core , mtl , prettyprinter@@ -67,6 +66,6 @@ build-depends: base >=4.7 && <5 , dhall >1.17- , hakyll+ , hakyll >=4.10 , hakyll-dhall default-language: Haskell2010
src/Hakyll/Web/Dhall.hs view
@@ -24,13 +24,17 @@ -- customizing rebuilding behavior for network, environment variable, and -- non-project local files. ----- 'loadDhall' and 'loadDhallExpr' allow for loading and parsing of Dhall--- files for usage within the 'Compiler' monad, so you can use the results--- as intermediate parts in building your pages. 'parseDhall' allows--- directly passing in Dhall strings to parse and resolve, tracking--- imports. 'dhallCompiler' is meant as a "final end-point", which just--- pretty-prints a parsed Dhall file, with optional normalization.-+-- There are three major workflows:+--+-- 1. 'dExprCompiler', 'loadDhall', and 'dhallCompiler', for loading+-- underlying Dhall files, saving them into the Hakyll cache and later+-- interpreting them as values.+--+-- 2. 'parseDhall' and 'parseDhallExpr', for parsing Dhall expressions+-- provided as strings, and resolving them while tracking dependencies.+--+-- 3. 'dhallPrettyCompiler', for processing and re-formatting Dhall+-- files and presenting them as-is as a "final end-point". module Hakyll.Web.Dhall ( -- * Configuration and Options@@ -38,20 +42,25 @@ , defaultDhallCompilerOptions, dcoResolver, dcoMinimize, dcoNormalize -- ** Resolver Behaviors , DhallResolver(..), DefaultDhallResolver(..), drRemap, drFull- -- * Load Dhall Files- -- ** As as custom Haskell types- , loadDhall, loadDhallWith- -- ** As raw expressions- , loadDhallExpr, loadDhallExprWith+ -- * Import and Load Dhall Files+ -- ** As Dhall expressions , DExpr(..)- -- * Parse raw Dhall expressions+ , dExprCompiler, dExprCompilerWith+ -- *** From Hakyll cache+ , loadDhall, loadDhallSnapshot+ -- ** As Haskell types+ , dhallCompiler, dhallCompilerWith+ -- * Parse Dhall+ -- ** As Haskell types , parseDhall, parseDhallWith- -- * Compile (prettify, normalize, re-map) Dhall Files- , dhallCompiler- , dhallRawCompiler, dhallFullCompiler- , dhallCompilerWith+ -- ** As Dhall Expressions+ , parseDhallExpr, parseDhallExprWith+ -- * Compile (prettify, normalize, re-map) Dhall text files+ , dhallPrettyCompiler+ , dhallRawPrettyCompiler, dhallFullPrettyCompiler+ , dhallPrettyCompilerWith -- * Internal Utilities- , parseRawDhallWith+ , parseRawDhallExprWith , resolveDhallImports ) where @@ -63,7 +72,7 @@ import Data.IORef import Data.Maybe import Data.Typeable (Typeable)-import Dhall hiding (maybe)+import Dhall import Dhall.Binary import Dhall.Core import Dhall.Diff@@ -140,15 +149,15 @@ -- | Types of external imports that a Dhall file may have. data DhallCompilerTrust = DCTLocal- -- ^ File on local filesystem outside of- -- project directory, and therefore not tracked- -- by Hakyll+ -- ^ File on local filesystem outside of+ -- project directory, and therefore not tracked+ -- by Hakyll | DCTRemote- -- ^ Link to remote resource over a network- -- connection+ -- ^ Link to remote resource over a network+ -- connection | DCTEnv- -- ^ Reference to environment variable on- -- machine+ -- ^ Reference to environment variable on+ -- machine deriving (Generic, Typeable, Show, Eq, Ord) -- | Options for loading Dhall files.@@ -157,8 +166,8 @@ -- ^ Method to resolve imports encountered in files. See -- documentation of 'DhallResolver' for more details. , _dcoMinimize :: Bool- -- ^ Strictly for usage with 'dhallCompiler' and family: should the- -- result be "minimized" (all in one line) or pretty-printed for+ -- ^ Strictly for usage with 'dhallPrettyCompiler' and family: should+ -- the result be "minimized" (all in one line) or pretty-printed for -- human readability? -- -- Can be useful for saving bandwidth.@@ -286,16 +295,16 @@ -- /TypeApplications/. -- -- @--- 'dhallRawCompiler' = 'dhallCompiler' \@'Import'--- 'dhallFullCompiler' = 'dhallCompiler' \@'X'+-- 'dhallRawPrettyCompiler' = 'dhallPrettyCompiler' \@'Import'+-- 'dhallFullPrettyCompiler' = 'dhallPrettyCompiler' \@'X' -- @ -- -- It might be more convenient to just use 'dhallRawCompiler' or -- 'dhallFullCompiler'.-dhallCompiler+dhallPrettyCompiler :: forall a. (DefaultDhallResolver a, PP.Pretty a) => Compiler (Item String)-dhallCompiler = dhallCompilerWith @a defaultDhallCompilerOptions+dhallPrettyCompiler = dhallPrettyCompilerWith @a defaultDhallCompilerOptions -- TODO: way to only resolve Env and Absolute and Home? -- Need to somehow hook into 'loadWith' so it can be recursive@@ -304,25 +313,23 @@ -- 'DhallCompilerOptions' while leaving all imports unchanged and -- unresolved. Essentially a Dhall pretty-printer, (optional) normalizer, -- and re-formatter.-dhallRawCompiler :: Compiler (Item String)-dhallRawCompiler = dhallCompilerWith @Import defaultDhallCompilerOptions+dhallRawPrettyCompiler :: Compiler (Item String)+dhallRawPrettyCompiler = dhallPrettyCompilerWith @Import defaultDhallCompilerOptions -- | Compile the Dhall file as text according to default -- 'DhallCompilerOptions', resolving all imports in IO and tracking -- dependencies. Essentially a Dhall pretty-printer, (optional) -- normalizer, and re-formatter.-dhallFullCompiler :: Compiler (Item String)-dhallFullCompiler = dhallCompilerWith @X defaultDhallCompilerOptions+dhallFullPrettyCompiler :: Compiler (Item String)+dhallFullPrettyCompiler = dhallPrettyCompilerWith @X defaultDhallCompilerOptions --- | 'dhallCompiler', but with custom 'DhallCompilerOptions'.-dhallCompilerWith+-- | 'dhallPrettyCompiler', but with custom 'DhallCompilerOptions'.+dhallPrettyCompilerWith :: PP.Pretty a => DhallCompilerOptions a -> Compiler (Item String)-dhallCompilerWith dco = do- i <- getUnderlying- b <- T.pack . itemBody <$> getResourceBody- e <- parseDhallWith dco (Just i) b+dhallPrettyCompilerWith dco = do+ DExpr e <- itemBody <$> dExprCompilerWith dco makeItem $ T.unpack (disp e) where disp@@ -332,56 +339,186 @@ . PP.unAnnotate . prettyExpr --- | Version of 'parseDhallWith' that only acceps the 'DRRaw' resolver,--- remapping the imports with the function in the 'DRRaw'. Does not--- perform any normalization.-parseRawDhallWith- :: DhallCompilerOptions Import- -> Maybe Identifier- -> T.Text- -> Compiler (Expr Src Import)-parseRawDhallWith DCO{..} i b =- case exprFromText (maybe "Raw dhall string" toFilePath i) b of- Left e -> throwError . (:[]) $- "Error parsing raw dhall file: " ++ show e- Right e -> join <$> traverse (_drRemap _dcoResolver) e+-- | Compile the underlying text file as a Dhall expression, wrapped in+-- a 'DExpr' newtype. Mostly useful for pre-cacheing fully resolved Dhall+-- expressions into the Hakyll cache, which you can later interpret and+-- load with 'loadDhall' or 'loadDhallSnapshot'. A @'DExpr' a@ is an+-- @'Expr' 'Src' a@, but wrapped so that it has a 'Bi.Binary' instance that+-- is usable by the Hakyll cache.+--+-- For example, here is a rule to parse and cache all configuration files:+--+-- @+-- 'match' "config/**.dhall" $ do+-- 'route' 'mempty'+-- 'compile' $ 'dExprCompiler' \@'X'+-- @+--+-- This will save all of the dhall files in the directory ./config in the+-- Hakyll cache. They can later be loaded and interpreted in the+-- 'Compiler' monad using:+--+-- @+-- 'loadDhall' 'auto' "config/my_config.dhall"+-- @+--+-- Note that this is mostly useful for routes that match many different+-- files which will be interpreted as values of different types, or for+-- caching a single expression that you might want to interpret as+-- different types later.+--+-- If you want to parse and immediately interpret, see 'dhallCompiler'.+dExprCompiler :: DefaultDhallResolver a => Compiler (Item (DExpr a))+dExprCompiler = dExprCompilerWith defaultDhallCompilerOptions +-- | 'dExprCompiler', but with custom 'DhallCompilerOptions'.+dExprCompilerWith+ :: DhallCompilerOptions a+ -> Compiler (Item (DExpr a))+dExprCompilerWith dco = do+ b <- itemBody <$> getResourceBody+ d <- takeDirectory . toFilePath <$> getUnderlying+ makeItem . DExpr =<< parseDhallExprWith dco (Just d) (T.pack b)++-- | Parse the underlying text file as a Dhall expression and directly+-- interpret it as a value of the given type. Tracks all dependencies, so+-- will trigger rebuilds based on downstream changes.+dhallCompiler+ :: Type a+ -> Compiler (Item a)+dhallCompiler = dhallCompilerWith defaultDhallCompilerOptions++-- | 'dhallCompiler', but with custom 'DhallCompilerOptions'.+dhallCompilerWith+ :: DhallCompilerOptions X+ -> Type a+ -> Compiler (Item a)+dhallCompilerWith dco t = do+ DExpr e <- itemBody <$> dExprCompilerWith dco+ makeItem =<< interpretDhallCompiler t e++-- | Wrapper over 'load' and 'interpretDhallCompiler'. Pulls up a 'DExpr'+-- compiled or saved into the Hakyll cache and interprets it as a value.+--+-- Expects item at identifier to be saved as @'DExpr' 'X'@ (possibly using+-- @'dExprCompiler' \@'X'@)+loadDhall+ :: Type a+ -> Identifier+ -> Compiler (Item a)+loadDhall t i = do+ DExpr e <- loadBody i+ makeItem =<< interpretDhallCompiler t e++-- | Wrapper over 'loadSnapshot' and 'interpretDhallCompiler'. Pulls up+-- a 'DExpr' saved into the Hakyll cache as a snapshot and interprets it as+-- a value.+--+-- Expects item at identifier to be saved as @'DExpr' 'X'@ (possibly using+-- @'dExprCompiler' \@'X'@)+loadDhallSnapshot+ :: Type a+ -> Identifier+ -> Snapshot+ -> Compiler (Item a)+loadDhallSnapshot t i s = do+ DExpr e <- loadSnapshotBody i s+ makeItem =<< interpretDhallCompiler t e+ -- | Parse a Dhall source. Meant to be useful for patterns similar to -- @dhall-to-text@. If using examples from -- <https://github.com/dhall-lang/dhall-text>, you can use: -- -- @--- 'parseDhall' 'Nothing' ".\/make-items .\/people"+-- 'parseDhallExpr' 'Nothing' ".\/make-items .\/people" -- @ -- -- Any local dependencies within the project directory (./make-items and -- ./people above, for example) are tracked by Hakyll, and so modifications -- to required files will also cause upstream files to be rebuilt.+--+-- To directly obtain a Dhall expression, see 'parseDhallExpr'. parseDhall- :: DefaultDhallResolver a- => Maybe Identifier -- ^ Optional 'Identifier' used to specify directory root for imports+ :: Type a+ -> Maybe FilePath -- ^ Override directory root -> T.Text- -> Compiler (Expr Src a)+ -> Compiler (Item a) parseDhall = parseDhallWith defaultDhallCompilerOptions -- | Version of 'parseDhall' taking custom 'DhallCompilerOptions'. parseDhallWith+ :: DhallCompilerOptions X+ -> Type a+ -> Maybe FilePath -- ^ Override directory root+ -> T.Text+ -> Compiler (Item a)+parseDhallWith dco t fp b = do+ e <- parseDhallExprWith dco fp b+ makeItem =<< interpretDhallCompiler t e++-- | Interpret a fully resolved Dhall expression as a value of a type,+-- given a 'Type'. Run in 'Compiler' to integrate error handling with+-- Hakyll.+interpretDhallCompiler+ :: Type a+ -> Expr Src X+ -> Compiler a+interpretDhallCompiler t e = case rawInput t e of+ Nothing -> throwError . (terr:) . (:[]) $ case typeOf e of+ Left err -> show err+ Right t0 -> T.unpack+ . PP.renderStrict+ . PP.layoutSmart layoutOpts+ . diffNormalized (expected t)+ $ t0+ Just x -> pure x+ where+ terr = "Error interpreting Dhall expression as desired type."++-- | Version of 'parseDhall' that directly returns a Dhall expression,+-- instead of trying to interpret it into a custom Haskell type.+--+-- Any local dependencies within the project directory (./make-items and+-- ./people above, for example) are tracked by Hakyll, and so modifications+-- to required files will also cause upstream files to be rebuilt.+parseDhallExpr+ :: DefaultDhallResolver a+ => Maybe FilePath -- ^ Override directory root+ -> T.Text+ -> Compiler (Expr Src a)+parseDhallExpr = parseDhallExprWith defaultDhallCompilerOptions++-- | Version of 'parseDhallExpr' taking custom 'DhallCompilerOptions'.+parseDhallExprWith :: DhallCompilerOptions a- -> Maybe Identifier -- ^ Optional 'Identifier' used to specify directory root for imports+ -> Maybe FilePath -- ^ Override directory root -> T.Text -> Compiler (Expr Src a)-parseDhallWith dco i b = case _dcoResolver dco of- DRRaw _ -> norm <$> parseRawDhallWith dco i b+parseDhallExprWith dco d b = case _dcoResolver dco of+ DRRaw _ -> norm <$> parseRawDhallExprWith dco b DRFull _ -> fmap norm- . resolveDhallImports dco i- =<< parseRawDhallWith (dco { _dcoResolver = defaultDhallResolver })- i b+ . resolveDhallImports dco d+ =<< parseRawDhallExprWith (dco { _dcoResolver = defaultDhallResolver })+ b where norm :: Eq b => Expr s b -> Expr s b norm | _dcoNormalize dco = normalize | otherwise = id +-- | Version of 'parseDhallExprWith' that only acceps the 'DRRaw' resolver,+-- remapping the imports with the function in the 'DRRaw'. Does not+-- perform any normalization.+parseRawDhallExprWith+ :: DhallCompilerOptions Import+ -> T.Text+ -> Compiler (Expr Src Import)+parseRawDhallExprWith DCO{..} b =+ case exprFromText "Hakyll.Web.Dhall.parseRawDhallExprWith" b of+ Left e -> throwError . (:[]) $+ "Error parsing raw dhall file: " ++ show e+ Right e -> join <$> traverse (_drRemap _dcoResolver) e+ -- | Resolve all imports in a parsed Dhall expression. -- -- This implements the "magic" of dependency tracking: implemented so that@@ -390,14 +527,14 @@ -- files to be rebuilt. resolveDhallImports :: DhallCompilerOptions X- -> Maybe Identifier -- ^ Optional 'Identifier' used to specify directory root for imports+ -> Maybe FilePath -- ^ Override directory root -> Expr Src Import -> Compiler (Expr Src X)-resolveDhallImports DCO{..} ident e = do+resolveDhallImports DCO{..} d e = do (res, imps) <- unsafeCompiler $ do iRef <- newIORef [] res <- evalStateT (loadWith e) $- emptyStatus (takeDirectory (maybe "./" toFilePath ident))+ emptyStatus (fromMaybe "./" d) & resolver .~ \i -> do liftIO $ modifyIORef iRef (i:) exprFromImport i@@ -426,52 +563,3 @@ | otherwise -> Just neverTrust Missing -> Just neverTrust neverTrust = PatternDependency mempty mempty---- | Load and parse the body of the given 'Identifier' as a Dhall--- expression.------ If you wrap the result in 'DExpr', you can save the result as--- a snapshot.-loadDhallExpr- :: DefaultDhallResolver a- => Identifier- -> Compiler (Item (Expr Src a))-loadDhallExpr = loadDhallExprWith defaultDhallCompilerOptions---- | Version of 'loadDhallExpr' taking custom 'DhallCompilerOptions'.-loadDhallExprWith- :: DhallCompilerOptions a- -> Identifier- -> Compiler (Item (Expr Src a))-loadDhallExprWith dco i = do- b <- T.pack <$> loadBody i- Item i <$> parseDhallWith dco (Just i) b---- | Load a value of type @a@ that is parsed from a Dhall file at the given--- 'Identifier'. Tracks dependencies within project.-loadDhall- :: Type a- -> Identifier- -> Compiler (Item a)-loadDhall = loadDhallWith defaultDhallCompilerOptions---- | Version of 'loadDhall' taking custom 'DhallCompilerOptions'.-loadDhallWith- :: DhallCompilerOptions X- -> Type a- -> Identifier- -> Compiler (Item a)-loadDhallWith dco t ident = traverse (inp t)- =<< loadDhallExprWith dco ident- where- inp :: Type a -> Expr Src X -> Compiler a- inp t' e = case rawInput t' e of- Nothing -> throwError . (terr:) . (:[]) $ case typeOf e of- Left err -> show err- Right t0 -> T.unpack- . PP.renderStrict- . PP.layoutSmart layoutOpts- . diffNormalized (expected t)- $ t0- Just x -> pure x- terr = "Error interpreting Dhall expression as desired type."