packages feed

ede 0.3.3.0 → 0.3.4.0

raw patch · 20 files changed

+306/−47 lines, 20 filesdep +attoparsec-aesondep ~aesondep ~optparse-applicativePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: attoparsec-aeson

Dependency ranges changed: aeson, optparse-applicative

API changes (from Hackage documentation)

- Text.EDE.Internal.Quoting: instance Text.EDE.Internal.Quoting.Quote GHC.Integer.Type.Integer
- Text.EDE.Internal.Quoting: instance Text.EDE.Internal.Quoting.Unquote GHC.Integer.Type.Integer
+ Text.EDE.Internal.AST: eOverrideBlock :: Id -> Exp a -> Exp a -> Exp a
+ Text.EDE.Internal.AST: eblock :: Id -> Exp a -> Exp a
+ Text.EDE.Internal.AST: eset :: Id -> Exp a -> Exp a -> Exp a
+ Text.EDE.Internal.Eval: [_blocks] :: Env -> HashMap Id (Exp Delta)
+ Text.EDE.Internal.Eval: [_extends] :: Env -> Bool
+ Text.EDE.Internal.Eval: bindBlock :: (HashMap Id (Exp Delta) -> HashMap Id (Exp Delta)) -> Context a -> Context a
+ Text.EDE.Internal.Eval: setExtended :: Bool -> Context a -> Context a
+ Text.EDE.Internal.Parser: [_blocks] :: Env -> HashMap Text (Exp Delta)
+ Text.EDE.Internal.Parser: [_extends] :: Env -> HashMap Text (NonEmpty Delta)
+ Text.EDE.Internal.Parser: block' :: Parser m => m (Exp Delta)
+ Text.EDE.Internal.Parser: blocks :: Lens' Env (HashMap Text (Exp Delta))
+ Text.EDE.Internal.Parser: extends :: Lens' Env (HashMap Text (NonEmpty Delta))
+ Text.EDE.Internal.Parser: extends' :: Parser m => m (Exp Delta)
+ Text.EDE.Internal.Parser: set :: Parser m => m (Exp Delta)
+ Text.EDE.Internal.Quoting: instance Text.EDE.Internal.Quoting.Quote GHC.Num.Integer.Integer
+ Text.EDE.Internal.Quoting: instance Text.EDE.Internal.Quoting.Unquote GHC.Num.Integer.Integer
+ Text.EDE.Internal.Types: EBlock :: !Id -> !a -> ExpF a
+ Text.EDE.Internal.Types: EExt :: !Text -> ExpF a
+ Text.EDE.Internal.Types: EOverrideBlock :: !Id -> !a -> !a -> ExpF a
+ Text.EDE.Internal.Types: [_tmplBlocks] :: Template -> HashMap Id (Exp Delta)
+ Text.EDE.Internal.Types: [_tmplExtends] :: Template -> HashMap Id (Exp Delta)
- Text.EDE: (.=) :: (KeyValue kv, ToJSON v) => Key -> v -> kv
+ Text.EDE: (.=) :: (KeyValue e kv, ToJSON v) => Key -> v -> kv
- Text.EDE: data Delta
+ Text.EDE: data () => Delta
- Text.EDE: delimBlock :: HasSyntax c_adP9 => Lens' c_adP9 Delim
+ Text.EDE: delimBlock :: HasSyntax c_aeaW => Lens' c_aeaW Delim
- Text.EDE: delimComment :: HasSyntax c_adP9 => Lens' c_adP9 Delim
+ Text.EDE: delimComment :: HasSyntax c_aeaW => Lens' c_aeaW Delim
- Text.EDE: delimInline :: HasSyntax c_adP9 => Lens' c_adP9 Delim
+ Text.EDE: delimInline :: HasSyntax c_aeaW => Lens' c_aeaW Delim
- Text.EDE: delimPragma :: HasSyntax c_adP9 => Lens' c_adP9 Delim
+ Text.EDE: delimPragma :: HasSyntax c_aeaW => Lens' c_aeaW Delim
- Text.EDE.Internal.Eval: Env :: HashMap Id (Exp Delta) -> HashMap Id Term -> HashMap Id Value -> Env
+ Text.EDE.Internal.Eval: Env :: Bool -> HashMap Id (Exp Delta) -> HashMap Id Term -> HashMap Id Value -> HashMap Id (Exp Delta) -> Env
- Text.EDE.Internal.Parser: Env :: !Syntax -> HashMap Text (NonEmpty Delta) -> Env
+ Text.EDE.Internal.Parser: Env :: !Syntax -> HashMap Text (NonEmpty Delta) -> HashMap Text (NonEmpty Delta) -> HashMap Text (Exp Delta) -> Env
- Text.EDE.Internal.Parser: runParser :: Syntax -> Text -> ByteString -> Result (Exp Delta, HashMap Text (NonEmpty Delta))
+ Text.EDE.Internal.Parser: runParser :: Syntax -> Text -> ByteString -> Result (Exp Delta, HashMap Text (NonEmpty Delta), HashMap Text (NonEmpty Delta), HashMap Text (Exp Delta))
- Text.EDE.Internal.Types: Template :: !Text -> !Exp Delta -> HashMap Id (Exp Delta) -> Template
+ Text.EDE.Internal.Types: Template :: !Text -> !Exp Delta -> HashMap Id (Exp Delta) -> HashMap Id (Exp Delta) -> HashMap Id (Exp Delta) -> Template
- Text.EDE.Internal.Types: _Failure :: forall a_abTC. Prism' (Result a_abTC) AnsiDoc
+ Text.EDE.Internal.Types: _Failure :: forall a_ackG. Prism' (Result a_ackG) AnsiDoc
- Text.EDE.Internal.Types: _Success :: forall a_adyU a_abTC. Prism (Result a_adyU) (Result a_abTC) a_adyU a_abTC
+ Text.EDE.Internal.Types: _Success :: forall a_adTF a_ackG. Prism (Result a_adTF) (Result a_ackG) a_adTF a_ackG
- Text.EDE.Internal.Types: class HasSyntax c_adP9
+ Text.EDE.Internal.Types: class HasSyntax c_aeaW
- Text.EDE.Internal.Types: delimBlock :: HasSyntax c_adP9 => Lens' c_adP9 Delim
+ Text.EDE.Internal.Types: delimBlock :: HasSyntax c_aeaW => Lens' c_aeaW Delim
- Text.EDE.Internal.Types: delimComment :: HasSyntax c_adP9 => Lens' c_adP9 Delim
+ Text.EDE.Internal.Types: delimComment :: HasSyntax c_aeaW => Lens' c_aeaW Delim
- Text.EDE.Internal.Types: delimInline :: HasSyntax c_adP9 => Lens' c_adP9 Delim
+ Text.EDE.Internal.Types: delimInline :: HasSyntax c_aeaW => Lens' c_aeaW Delim
- Text.EDE.Internal.Types: delimPragma :: HasSyntax c_adP9 => Lens' c_adP9 Delim
+ Text.EDE.Internal.Types: delimPragma :: HasSyntax c_aeaW => Lens' c_aeaW Delim
- Text.EDE.Internal.Types: syntax :: HasSyntax c_adP9 => Lens' c_adP9 Syntax
+ Text.EDE.Internal.Types: syntax :: HasSyntax c_aeaW => Lens' c_aeaW Syntax

Files

app/Main.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} @@ -5,6 +6,9 @@  import qualified Control.Monad.Fail as Fail import qualified Data.Aeson as Aeson+#ifdef VERSION_attoparsec_aeson+import qualified Data.Aeson.Parser as Aeson+#endif import qualified Data.Attoparsec.ByteString as Parsec import qualified Data.ByteString as ByteString import qualified Data.ByteString.Lazy as ByteString.Lazy@@ -41,8 +45,8 @@           ( Options.long "context-file"               <> Options.metavar "PATH"               <> Options.help-                "Path of a file containing a JSON object which is used \-                \as the template context"+                ("Path of a file containing a JSON object which is used " <>+                 "as the template context")           )       )     <*> Options.optional@@ -63,26 +67,32 @@   where     usage =       Pretty.vcat-        [ Pretty.empty,+        [ Pretty.emptyDoc,           "The --context-file and --context-json options are processed as follows:",           Pretty.indent 2 "1.)"             Pretty.<+> ( Pretty.align-                           ( "Both are provided"-                               Pretty.<$$> "Both objects are merged into one with the keys of \-                                           \--context-json taking precedence over those in the \-                                           \file provided by --context-file."+                           ( Pretty.vcat+                               [ "Both are provided",+                                 "Both objects are merged into one with the keys of " <>+                                 "--context-json taking precedence over those in the " <>+                                 "file provided by --context-file."+                               ]                            )                        ),           Pretty.indent 2 "2.)"             Pretty.<+> ( Pretty.align-                           ( "None of them are provided"-                               Pretty.<$$> "The JSON object is read from STDIN."+                           ( Pretty.vcat+                               [ "None of them are provided",+                                 "The JSON object is read from STDIN."+                               ]                            )                        ),           Pretty.indent 2 "3.)"             Pretty.<+> ( Pretty.align-                           ( "One of them is provided"-                               Pretty.<$$> "The JSON object is read from the supplied option."+                           ( Pretty.vcat+                               [ "One of them is provided",+                                 "The JSON object is read from the supplied option."+                               ]                            )                        )         ]
ede.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.2 name:               ede-version:            0.3.3.0+version:            0.3.4.0 synopsis:   Templating language with similar syntax and features to Liquid or Jinja2. @@ -9,7 +9,7 @@ license-file:       LICENSE author:             Brendan Hay maintainer:         Brendan Hay <brendan.g.hay@gmail.com>-copyright:          Copyright (c) 2013-2020 Brendan Hay+copyright:          Copyright (c) 2013-2022 Brendan Hay stability:          Experimental category:           Text, Template, Web build-type:         Simple@@ -45,6 +45,9 @@   type:     git   location: git://github.com/brendanhay/ede.git +flag AttoparsecAeson+  description: Build attoparsec-aeson.+ common base   default-language: Haskell2010   ghc-options:@@ -95,15 +98,22 @@   main-is:        Main.hs   ghc-options:    -threaded -rtsopts -with-rtsopts=-A128m   build-depends:-    , aeson                        >=1.4     , attoparsec                   >=0.13     , bytestring                   >=0.10.4     , ede-    , optparse-applicative         >=0.11-    , prettyprinter                >= 1.7+    , optparse-applicative         >=0.18+    , prettyprinter                >=1.7     , prettyprinter-ansi-terminal  >=1.1     , text                         >=1.2     , unordered-containers         >=0.2.3++  if flag(AttoparsecAeson)+    build-depends:+      , aeson                      >=2.2+      , attoparsec-aeson           >=2.2+  else+    build-depends:+      , aeson                      >=1.4  test-suite tests   import:         base
lib/Text/EDE.hs view
@@ -3,7 +3,7 @@  -- | -- Module      : Text.EDE--- Copyright   : (c) 2013-2020 Brendan Hay <brendan.g.hay@gmail.com>+-- Copyright   : (c) 2013-2022 Brendan Hay <brendan.g.hay@gmail.com> -- License     : This Source Code Form is subject to the terms of --               the Mozilla Public License, v. 2.0. --               A copy of the MPL can be found in the LICENSE file or@@ -109,6 +109,9 @@      -- ** Let Expressions     -- $let++    -- ** Set+    -- $set   ) where @@ -211,14 +214,15 @@   -- | Strict 'ByteString' template definition.   ByteString ->   m (Result Template)-parseWith config f name =-  result failure resolve-    . Parser.runParser config name+parseWith config f name input =+  case Parser.runParser config name input of+    Success (u, is', es', bs) -> do+      is <- Foldable.foldrM include (Success (HashMap.singleton name u)) (HashMap.toList is')+      es <- Foldable.foldrM extends (Success mempty) (HashMap.toList es')+      pure (Template name u <$> is <*> es <*> pure bs)+    Failure err ->+      failure err   where-    resolve (u, is) =-      Foldable.foldrM include (Success (HashMap.singleton name u)) (HashMap.toList is)-        >>= result failure (success . Template name u)-     -- Presuming self is always in self's includes, see singleton above.     -- FIXME: utilise the list of deltas for failures     include (_, _) (Failure err) = failure err@@ -226,6 +230,11 @@       f config key delta         >>= result failure (success . mappend ss . _tmplIncl) +    extends (_, _) (Failure err) = failure err+    extends (key, delta :| _) (Success ss) =+      f config key delta+        >>= result failure (success . mappend ss . _tmplIncl)+ -- | 'HashMap' resolver for @include@ expressions. -- -- The 'identifier' component of the @include@ expression is treated as a lookup@@ -288,8 +297,12 @@   -- | Bindings to make available in the environment.   HashMap Text Value ->   Result Text.Lazy.Text-renderWith fs (Template _ u ts) =-  fmap Text.Builder.toLazyText . Eval.render ts fs u+renderWith fs t =+  fmap Text.Builder.toLazyText .+    Eval.render+      (_tmplIncl t <> _tmplExtends t)+      fs+      (_tmplExp t)  -- | /See:/ 'parse' eitherParse :: ByteString -> Either String Template@@ -696,3 +709,55 @@ -- > {{ var }} -- > ... -- > {% endlet %}++-- $set+--+-- You can also bind an identifier to whole templates which will be available within+-- the following expression scope. The identifier will be available in subsequent template.+--+-- For example:+--+-- > {% set var %}+-- >   ...+-- > {% endset %}+-- > ...+-- > {{ var }}++-- $block+--+-- Blocks are used for inheritance and act as both placeholders and replacements at the same time: The most powerful+-- part of @ED-E@ is template inheritance. Template inheritance allows you to build a base "skeleton" template that+-- contains all the common elements of your site and defines blocks that child templates can override.+--+-- Base template:+--+-- > <!doctype html>+-- > {% block head %}+-- > <title>{% block title %}{% endblock %}</title>+-- > {% endblock %}+-- > {% block body %}{% endblock %}+--+-- Child template:+--+-- > {% extends "base.html" %}+-- > {% block title %}Index{% endblock %}+-- > {% block head %}+-- >  {{ super }}+-- >  <style type="text/css">+-- >   .important { color: #336699; }+-- > </style>+-- > {% endblock %}+-- > {% block body %}+-- >  <h1>Index</h1>+-- >  <p class="important">+-- >    Welcome to my awesome homepage.+-- >  </p>+-- > {% endblock %}+--+-- The @{% extends %}@ tag is the key here. It tells the template engine that this template "extends" another template.+-- When the template system evaluates this template, it first locates the parent. The extends tag should be the first tag in the template.+--+-- As you can see it's also possible to render the contents of the parent block by calling super(). You can’t define multiple {% block %}+-- tags with the same name in the same template. This limitation exists because a block tag works in “both” directions. That is, a block+-- tag doesn’t just provide a placeholder to fill - it also defines the content that fills the placeholder in the parent. If there were two+-- similarly-named {% block %} tags in a template, that template's parent wouldn’t know which one of the blocks’ content to use.
lib/Text/EDE/Filters.hs view
@@ -1,6 +1,6 @@ -- | -- Module      : Text.EDE.Filters--- Copyright   : (c) 2013-2020 Brendan Hay <brendan.g.hay@gmail.com>+-- Copyright   : (c) 2013-2022 Brendan Hay <brendan.g.hay@gmail.com> -- License     : This Source Code Form is subject to the terms of --               the Mozilla Public License, v. 2.0. --               A copy of the MPL can be found in the LICENSE file or
lib/Text/EDE/Internal/AST.hs view
@@ -3,7 +3,7 @@  -- | -- Module      : Text.EDE.Internal.AST--- Copyright   : (c) 2013-2020 Brendan Hay <brendan.g.hay@gmail.com>+-- Copyright   : (c) 2013-2022 Brendan Hay <brendan.g.hay@gmail.com> -- License     : This Source Code Form is subject to the terms of --               the Mozilla Public License, v. 2.0. --               A copy of the MPL can be found in the LICENSE file or@@ -56,6 +56,21 @@ elet :: Maybe (Id, Exp a) -> Exp a -> Exp a elet m e = maybe e (\(i, b) -> Comonad.extract b :< ELet i b e) m {-# INLINEABLE elet #-}++eset :: Id -> Exp a -> Exp a -> Exp a+eset i e k =+  elet (Just (i, e)) k+{-# INLINEABLE eset #-}++eblock :: Id -> Exp a -> Exp a+eblock i e =+  Comonad.extract e :< EBlock i e+{-# INLINEABLE eblock #-}++eOverrideBlock :: Id -> Exp a -> Exp a -> Exp a+eOverrideBlock i b e =+  Comonad.extract b :< EOverrideBlock i b e+{-# INLINEABLE eOverrideBlock #-}  ecase ::   Exp a ->
lib/Text/EDE/Internal/Eval.hs view
@@ -5,7 +5,7 @@  -- | -- Module      : Text.EDE.Internal.Eval--- Copyright   : (c) 2013-2020 Brendan Hay <brendan.g.hay@gmail.com>+-- Copyright   : (c) 2013-2022 Brendan Hay <brendan.g.hay@gmail.com> -- License     : This Source Code Form is subject to the terms of --               the Mozilla Public License, v. 2.0. --               A copy of the MPL can be found in the LICENSE file or@@ -49,9 +49,11 @@ import qualified Text.Trifecta.Delta as Trifecta.Delta  data Env = Env-  { _templates :: HashMap Id (Exp Delta),+  { _extends :: Bool,+    _templates :: HashMap Id (Exp Delta),     _quoted :: HashMap Id Term,-    _values :: HashMap Id Value+    _values :: HashMap Id Value,+    _blocks :: HashMap Id (Exp Delta)   }  type Context = ReaderT Env Result@@ -63,7 +65,7 @@   HashMap Id Value ->   Result Builder render ts fs e o =-  Reader.runReaderT (eval e >>= nf) (Env ts (stdlib <> fs) o)+  Reader.runReaderT (eval e >>= nf) (Env False ts (stdlib <> fs) o mempty)   where     nf (TVal v) = build (Trifecta.Delta.delta e) v     nf _ =@@ -85,6 +87,26 @@   x <- eval a   y <- eval b   binding d x y+eval (d :< EOverrideBlock i b e) =+  setExtended True $ do+    q <- HashMap.lookup i <$> Reader.asks _blocks+    case q of+      Nothing ->+        bindBlock (HashMap.insert i b) (eval e)+      Just eb ->+        bindBlock (HashMap.insert i (d :< ELet "super" b eb)) (eval e)+eval (_ :< EBlock i b) = do+  extends <- Reader.asks _extends+  q <- HashMap.lookup i <$> Reader.asks _blocks+  if extends then+    pure (qprim (String mempty))+  else do+    x <- eval b+    v <- lift (unquote i 0 x)+    maybe+      (pure x)+      (bind (HashMap.insert "super" v) . eval)+      q eval (_ :< ELet k rhs bdy) = do   q <- eval rhs   v <- lift (unquote k 0 q)@@ -164,18 +186,41 @@ eval (d :< EIncl i) = do   ts <- Reader.asks _templates   case HashMap.lookup i ts of-    Just e -> eval e+    Just e ->+      -- Don't inherit any blocks declared so far.+      setExtended False $+        bindBlock (\_ -> mempty) (eval e)     Nothing ->       throwError d $         "template"           <+> bold (pp i)           <+> "is not in scope:"           <+> PP.brackets (pp (Text.intercalate "," $ HashMap.keys ts))+eval (d :< EExt i) = do+  ts <- Reader.asks _templates+  case HashMap.lookup i ts of+    Just e ->+      setExtended False (eval e)+    Nothing ->+      throwError d $+        "template"+          <+> bold (pp i)+          <+> "is not in scope:"+          <+> PP.brackets (pp (Text.intercalate "," $ HashMap.keys ts)) {-# INLINEABLE eval #-}  bind :: (HashMap Text Value -> HashMap Text Value) -> Context a -> Context a bind f = Reader.withReaderT (\x -> x {_values = f (_values x)}) {-# INLINEABLE bind #-}++bindBlock :: (HashMap Id (Exp Delta) -> HashMap Id (Exp Delta)) -> Context a -> Context a+bindBlock f = Reader.withReaderT (\x -> x {_blocks = f (_blocks x)})+{-# INLINEABLE bindBlock #-}++setExtended :: Bool -> Context a -> Context a+setExtended extends =+  Reader.withReaderT (\x -> x { _extends = extends })+{-# INLINEABLE setExtended #-}  variable :: Delta -> Var -> Context Value variable d (Var is) =
lib/Text/EDE/Internal/Filters.hs view
@@ -8,7 +8,7 @@  -- | -- Module      : Text.EDE.Internal.Filters--- Copyright   : (c) 2013-2020 Brendan Hay <brendan.g.hay@gmail.com>+-- Copyright   : (c) 2013-2022 Brendan Hay <brendan.g.hay@gmail.com> -- License     : This Source Code Form is subject to the terms of --               the Mozilla Public License, v. 2.0. --               A copy of the MPL can be found in the LICENSE file or
lib/Text/EDE/Internal/Parser.hs view
@@ -11,7 +11,7 @@  -- | -- Module      : Text.EDE.Internal.Parser--- Copyright   : (c) 2013-2020 Brendan Hay <brendan.g.hay@gmail.com>+-- Copyright   : (c) 2013-2022 Brendan Hay <brendan.g.hay@gmail.com> -- License     : This Source Code Form is subject to the terms of --               the Mozilla Public License, v. 2.0. --               A copy of the MPL can be found in the LICENSE file or@@ -35,7 +35,6 @@ import qualified Control.Monad.State.Strict as State import Control.Monad.Trans (lift) import Data.Aeson.Types (Value (..))-import qualified Data.Bifunctor as Bifunctor import Data.ByteString (ByteString) import qualified Data.Char as Char import Data.HashMap.Strict (HashMap)@@ -64,7 +63,9 @@  data Env = Env   { _settings :: !Syntax,-    _includes :: HashMap Text (NonEmpty Delta)+    _includes :: HashMap Text (NonEmpty Delta),+    _extends :: HashMap Text (NonEmpty Delta),+    _blocks :: HashMap Text (Exp Delta)   }  $(Lens.makeLenses ''Env)@@ -120,15 +121,25 @@   Syntax ->   Text ->   ByteString ->-  Result (Exp Delta, HashMap Text (NonEmpty Delta))+  Result (Exp Delta, HashMap Text (NonEmpty Delta), HashMap Text (NonEmpty Delta), HashMap Text (Exp Delta)) runParser o n = res . Trifecta.parseByteString (runEDE run) pos   where-    run = State.runStateT (pragma *> document <* Trifecta.eof) (Env o mempty)+    run = State.runStateT (pragma *> document <* Trifecta.eof) (Env o mempty mempty mempty)      pos = Trifecta.Delta.Directed (Text.Encoding.encodeUtf8 n) 0 0 0 0      res = \case-      Trifecta.Success x -> Success (Bifunctor.second _includes x)+      Trifecta.Success (x, env) ->+        if null (_extends env) then+          Success (x, _includes env, _extends env, _blocks env)+        else+          -- In case the template extends another template we arrange the contained+          -- blocks in a way that make it easy to evaluate the "inheritance" mechanism.+          let+            x' =+              HashMap.foldrWithKey eOverrideBlock x (_blocks env)+          in+            Success (x', _includes env, _extends env, _blocks env)       Trifecta.Failure e -> Failure (Trifecta._errDoc e)  pragma :: Parser m => m ()@@ -184,6 +195,9 @@       cases,       loop,       include,+      set,+      block',+      extends',       binding,       raw,       comment@@ -257,6 +271,13 @@         (,) <$> (keyword "with" *> identifier)           <*> (Trifecta.symbol "=" *> term) +extends' :: Parser m => m (Exp Delta)+extends' = block "extends" $ do+  d <- Trifecta.position+  k <- Trifecta.stringLiteral+  extends %= HashMap.insertWith (<>) k (d :| [])+  pure (d :< EExt k)+ binding :: Parser m => m (Exp Delta) binding =   elet . Just@@ -267,6 +288,22 @@       )     <*> document     <* exit "endlet"++set :: Parser m => m (Exp Delta)+set =+  eset+  <$> block "set" identifier+  <*> document+  <* exit "endset"+  <*> document++block' :: Parser m => m (Exp Delta)+block' = do+  k <- block "block" identifier+  e <- document+  _ <- exit "endblock"+  blocks %= HashMap.insert k e+  pure (eblock k e)  raw :: Parser m => m (Exp Delta) raw = ann (ELit <$> body)
lib/Text/EDE/Internal/Quoting.hs view
@@ -8,7 +8,7 @@  -- | -- Module      : Text.EDE.Internal.Quoting--- Copyright   : (c) 2013-2020 Brendan Hay <brendan.g.hay@gmail.com>+-- Copyright   : (c) 2013-2022 Brendan Hay <brendan.g.hay@gmail.com> -- License     : This Source Code Form is subject to the terms of --               the Mozilla Public License, v. 2.0. --               A copy of the MPL can be found in the LICENSE file or
lib/Text/EDE/Internal/Syntax.hs view
@@ -2,7 +2,7 @@  -- | -- Module      : Text.EDE.Internal.Syntax--- Copyright   : (c) 2013-2020 Brendan Hay <brendan.g.hay@gmail.com>+-- Copyright   : (c) 2013-2022 Brendan Hay <brendan.g.hay@gmail.com> -- License     : This Source Code Form is subject to the terms of --               the Mozilla Public License, v. 2.0. --               A copy of the MPL can be found in the LICENSE file or@@ -104,7 +104,11 @@       "_",       ".",       "true",-      "false"+      "false",+      "set",+      "endset",+      "block",+      "endblock"     ]  pragmaStyle :: TokenParsing m => IdentifierStyle m
lib/Text/EDE/Internal/Types.hs view
@@ -11,7 +11,7 @@  -- | -- Module      : Text.EDE.Internal.Types--- Copyright   : (c) 2013-2020 Brendan Hay <brendan.g.hay@gmail.com>+-- Copyright   : (c) 2013-2022 Brendan Hay <brendan.g.hay@gmail.com> -- License     : This Source Code Form is subject to the terms of --               the Mozilla Public License, v. 2.0. --               A copy of the MPL can be found in the LICENSE file or@@ -166,7 +166,9 @@ data Template = Template   { _tmplName :: !Text,     _tmplExp :: !(Exp Delta),-    _tmplIncl :: HashMap Id (Exp Delta)+    _tmplIncl :: HashMap Id (Exp Delta),+    _tmplExtends :: HashMap Id (Exp Delta),+    _tmplBlocks :: HashMap Id (Exp Delta)   }   deriving (Eq) @@ -203,9 +205,12 @@   | EFun !Id   | EApp !a !a   | ELet !Id !a !a+  | EBlock !Id !a+  | EOverrideBlock !Id !a !a   | ECase !a [Alt a]   | ELoop !Id !a !a   | EIncl !Text+  | EExt !Text   deriving (Eq, Show, Functor)  instance Functor.Classes.Eq1 ExpF where@@ -214,11 +219,14 @@   liftEq _ (EFun a) (EFun b) = a == b   liftEq c (EApp a1 a2) (EApp b1 b2) = a1 `c` b1 && a2 `c` b2   liftEq c (ELet a0 a1 a2) (ELet b0 b1 b2) = a0 == b0 && a1 `c` b1 && a2 `c` b2+  liftEq c (EBlock a0 a1) (EBlock b0 b1) = a0 == b0 && a1 `c` b1+  liftEq c (EOverrideBlock a0 a1 a2) (EOverrideBlock b0 b1 b2) = a0 == b0 && a1 `c` b1 && a2 `c` b2   liftEq c (ECase a as) (ECase b bs) = a `c` b && (List.all (uncurry altEq) $ zip as bs)     where       altEq (pA, a') (pB, b') = pA == pB && a' `c` b'   liftEq c (ELoop a0 a1 a2) (ELoop b0 b1 b2) = a0 == b0 && a1 `c` b1 && a2 `c` b2   liftEq _ (EIncl a) (EIncl b) = a == b+  liftEq _ (EExt a) (EExt b) = a == b   liftEq _ _ _ = False  type Exp = Cofree ExpF
test/Main.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-}  -- Module      : Main--- Copyright   : (c) 2013-2020 Brendan Hay <brendan.g.hay@gmail.com>+-- Copyright   : (c) 2013-2022 Brendan Hay <brendan.g.hay@gmail.com> -- License     : This Source Code Form is subject to the terms of --               the Mozilla Public License, v. 2.0. --               A copy of the MPL can be found in the LICENSE file or
+ test/resources/ext-base.ede view
@@ -0,0 +1,7 @@+{}+---+<!doctype html>+{% block head %}+<title>{% block title %}{% endblock %}</title>+{% endblock %}+{% block body %}{% endblock %}
+ test/resources/ext-base.golden view
@@ -0,0 +1,2 @@+<!doctype html>+<title></title>
+ test/resources/ext-child.ede view
@@ -0,0 +1,16 @@+{}+---+{% extends "ext-base.ede" %}+{% block title %}Index{% endblock %}+{% block head %}+  {{ super }}+  <style type="text/css">+    .important { color: #336699; }+  </style>+{% endblock %}+{% block body %}+  <h1>Index</h1>+  <p class="important">+    Welcome to my awesome homepage.+  </p>+{% endblock %}
+ test/resources/ext-child.golden view
@@ -0,0 +1,13 @@+{}+---+<!doctype html>+  <title>Index</title>++  <style type="text/css">+    .important { color: #336699; }+  </style>+  <h1>Index</h1>+  <p class="important">+    Welcome to my awesome homepage.+  </p>+
test/resources/polymorphic-show.golden view
@@ -4,4 +4,4 @@ 1.0 ["a","b","c","d","e"] [1,2,3,4,5]-{"foo":"x","bar":"y"}+{"bar":"y","foo":"x"}
+ test/resources/set.ede view
@@ -0,0 +1,17 @@+{+  "var": true+}+---+{% set x %}++  {% set y %}+    This is a nested block {{var}}+  {% endset %}++  This is a big expression! {{var}}++  {{ y }}++{% endset %}++{{x}}
+ test/resources/set.golden view
@@ -0,0 +1,8 @@++++  This is a big expression! true++      This is a nested block true++
test/resources/whitespace.golden view
@@ -6,6 +6,8 @@     +               test  +