buffet-0.2.0: src/Buffet/Document/DocumentInternal.hs
module Buffet.Document.DocumentInternal
( get
) where
import qualified Buffet.Document.Configuration as Configuration
import qualified Buffet.Document.TemplateContext as TemplateContext
import qualified Buffet.Ir.Ir as Ir
import qualified Buffet.Toolbox.ExceptionTools as ExceptionTools
import qualified Buffet.Toolbox.TextTools as TextTools
import qualified Control.Exception as Exception
import qualified Data.Aeson as Aeson
import qualified Data.List.NonEmpty as NonEmpty
import qualified Data.Text as T
import Prelude
( FilePath
, IO
, Show
, ($)
, (.)
, (<>)
, fmap
, maybe
, pure
, show
, unlines
)
import qualified System.FilePath as FilePath
import qualified Text.Mustache as Mustache
import qualified Text.Mustache.Render as Render
import qualified Text.Mustache.Types as Types
import qualified Text.Parsec as Parsec
data Exception
= CompileException Parsec.ParseError
| SubstituteException FilePath (NonEmpty.NonEmpty Render.SubstitutionError)
instance Show Exception where
show (CompileException error) = show error
show (SubstituteException path errors) =
unlines . NonEmpty.toList . NonEmpty.cons (path <> ":") $ fmap show' errors
where
show' (Render.VariableNotFound name) =
"Variable not found: " <> showName name
show' (Render.InvalidImplicitSectionContextType valueType) =
"Invalid implicit section context type: " <> valueType
show' Render.InvertedImplicitSection = "Inverted implicit section"
show' (Render.SectionTargetNotFound name) =
"Section target not found: " <> showName name
show' (Render.PartialNotFound path') = "Partial not found: " <> path'
show' (Render.DirectlyRenderedValue value) =
"Directly rendered value: " <> show value
showName = T.unpack . T.intercalate (T.pack ".")
instance Exception.Exception Exception
get :: Configuration.Configuration -> Ir.Buffet -> IO T.Text
get configuration =
maybe
(pure . printTemplateContext)
renderTemplate
(Configuration.template configuration) .
TemplateContext.get
printTemplateContext :: Aeson.Value -> T.Text
printTemplateContext = TextTools.prettyPrintJson
renderTemplate :: FilePath -> Aeson.Value -> IO T.Text
renderTemplate templatePath templateContext = do
template <- getTemplate templatePath
let (errors, result) =
Mustache.checkedSubstitute template $ Types.mFromJSON templateContext
maybe (pure result) (Exception.throwIO . SubstituteException templatePath) $
NonEmpty.nonEmpty errors
getTemplate :: FilePath -> IO Mustache.Template
getTemplate templatePath =
ExceptionTools.eitherThrow CompileException $
Mustache.automaticCompile searchSpace templatePath
where
searchSpace = [".", FilePath.takeDirectory templatePath]