    {-|
    Module      : $Header$
    Description : Basic functions for dealing with mustache templates.
    Copyright   : (c) Justus Adam, 2015
    License     : BSD3
    Maintainer  : dev@justus.science
    Stability   : experimental
    Portability : POSIX

    = How to use this library

    This module exposes some of the most convenient functions for dealing with mustache
    templates.

    == Compiling with automatic partial discovery

    The easiest way of compiling a file and its potential includes (called partials)
    is by using the 'automaticCompile' function.

    @
    main :: IO ()
    main = do
      let searchSpace = [".", "./templates"]
          templateName = "main.mustache"

      compiled <- automaticCompile searchSpace templateName
      case compiled of
        Left err -> print err
        Right template -> return () -- this is where you can start using it
    @

    The @searchSpace@ encompasses all directories in which the compiler should
    search for the template source files.
    The search itself is conducted in order, from left to right.

    Should your search space be only the current working directory, you can use
    'localAutomaticCompile'.

    The @templateName@ is the relative path of the template to any directory
    of the search space.

    'automaticCompile' not only finds and compiles the template for you, it also
    recursively finds any partials included in the template as well,
    compiles them and stores them in the 'partials' hash attached to the resulting
    template.

    The compiler will throw errors if either the template is malformed
    or the source file for a partial or the template itself could not be found
    in any of the directories in @searchSpace@.

    == Substituting

    In order to substitute data into the template it must be an instance of the 'ToMustache'
    typeclass or be of type 'Value'.

    This libray tries to imitate the API of <https://hackage.haskell.org/package/aeson aeson>
    by allowing you to define conversions of your own custom data types into 'Value',
    the type used internally by the substitutor via typeclass and a selection of
    operators and convenience functions.

    === Example

    @
      data Person = { age :: Int, name :: String }

      instance ToMustache Person where
        toMustache person = object
          [ "age" ~> age person
          , "name" ~> name person
          ]
    @

    The values to the left of the '~>' operator has to be of type 'Text', hence the
    @OverloadedStrings@ can becomes very handy here.

    Values to the right of the '~>' operator must be an instance of the 'ToMustache'
    typeclass. Alternatively, if your value to the right of the '~>' operator is
    not an instance of 'ToMustache' but an instance of 'ToJSON' you can use the
    '~=' operator, which accepts 'ToJSON' values.

    @
      data Person = { age :: Int, name :: String, address :: Address }

      data Address = ...

      instance ToJSON Address where
        ...

      instance ToMustache Person where
        toMustache person = object
          [ "age" ~> age person
          , "name" ~> name person
          , "address" ~= address person
          ]
    @

    All operators are also provided in a unicode form, for those that, like me, enjoy
    unicode operators.

    == Manual compiling

    You can compile templates manually without requiring the IO monad at all, using
    the 'compileTemplate' function. This is the same function internally used by
    'automaticCompile' and does not check if required partial are present.

    More functions for manual compilation can be found in the 'Text.Mustache.Compile'
    module. Including helpers for finding lists of partials in templates.

    Additionally the 'compileTemplateWithCache' function is exposed here which you
    may use to automatically compile a template but avoid some of the compilation
    overhead by providing already compiled partials as well.

    == Fundamentals

    This library builds on three important data structures/types.

    ['Value'] A data structure almost identical to Data.Aeson.Value extended with
    lambda functions which represents the data the template is being filled with.

    ['ToMustache'] A typeclass for converting arbitrary types to 'Value', similar
    to Data.Aeson.ToJSON but with support for lambdas.

    ['Template'] Contains the 'STree', the syntax tree, which is basically a
    list of text blocks and mustache tags. The 'name' of the template and its
    'partials' cache.

    === Compiling

    During the compilation step the template file is located, read, then parsed in a single
    pass ('compileTemplate'), resulting in a 'Template' with an empty 'partials' section.

    Subsequenty the 'STree' of the template is scanned for included partials, any
    present 'TemplateCache' is queried for the partial ('compileTemplateWithCache'),
    if not found it will be searched for in the @searchSpace@, compiled and
    inserted into the template's own cache as well as the global cache for the
    compilation process.

    Internally no partial is compiled twice, as long as the names stay consistent.

    Once compiled templates may be used multiple times for substitution or as
    partial for other templates.

    Partials are not being embedded into the templates during compilation, but during
    substitution, hence the 'partials' cache is vital to the template even after
    compilation has been completed. Any non existent partial in the cache will
    rsubstitute to an empty string.

    === Substituting

    -}
    {-# LANGUAGE LambdaCase #-}
    module Text.Mustache
      (
      -- * Compiling

      -- ** Automatic
        automaticCompile, localAutomaticCompile

      -- ** Manually
      , compileTemplateWithCache, compileTemplate, Template(..)

      -- * Rendering

      -- ** Generic

      , substitute, checkedSubstitute

      -- ** Specialized

      , substituteValue, checkedSubstituteValue

      -- ** In Lambdas

      , substituteNode, substituteAST, catchSubstitute

      -- * Data Conversion
      , ToMustache, toMustache, object, (~>), (~=)

      -- ** Utilities for lambdas

      , overText

      ) where

    import           Text.Mustache.Compile
    import           Text.Mustache.Render
    import           Text.Mustache.Types
    import qualified Data.Text as T

    -- | Creates a 'Lambda' which first renders the contained section and then applies the supplied function
    overText :: (T.Text -> T.Text) -> Value
    overText :: (Text -> Text) -> Value
    overText f :: Text -> Text
    f = (STree -> SubM Text) -> Value
    forall ω. ToMustache ω => ω -> Value
    toMustache ((STree -> SubM Text) -> Value) -> (STree -> SubM Text) -> Value
    forall a b. (a -> b) -> a -> b
    $ (((), Text) -> Text) -> SubM ((), Text) -> SubM Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (Text -> Text
    f (Text -> Text) -> (((), Text) -> Text) -> ((), Text) -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((), Text) -> Text
    forall a b. (a, b) -> b
    snd) (SubM ((), Text) -> SubM Text)
    -> (STree -> SubM ((), Text)) -> STree -> SubM Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . SubM () -> SubM ((), Text)
    forall a. SubM a -> SubM (a, Text)
    catchSubstitute (SubM () -> SubM ((), Text))
    -> (STree -> SubM ()) -> STree -> SubM ((), Text)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . STree -> SubM ()
    substituteAST