packages feed

heterocephalus 1.0.4.0 → 1.0.5.0

raw patch · 7 files changed

+140/−43 lines, 7 filesdep +mtldep +transformersPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: mtl, transformers

API changes (from Hackage documentation)

+ Text.Heterocephalus: ParseOptions :: Char -> Char -> ParseOptions
+ Text.Heterocephalus: [parseOptionsControlPrefix] :: ParseOptions -> Char
+ Text.Heterocephalus: [parseOptionsVariablePrefix] :: ParseOptions -> Char
+ Text.Heterocephalus: [parseOptions] :: HeterocephalusSetting -> ParseOptions
+ Text.Heterocephalus: createParseOptions :: Char -> Char -> ParseOptions
+ Text.Heterocephalus: data ParseOptions
+ Text.Heterocephalus: defaultParseOptions :: ParseOptions
- Text.Heterocephalus: HeterocephalusSetting :: Q Exp -> HeterocephalusSetting
+ Text.Heterocephalus: HeterocephalusSetting :: Q Exp -> ParseOptions -> HeterocephalusSetting

Files

CHANGELOG.md view
@@ -1,6 +1,17 @@ Change Log ========== +Version 1.0.5.0 (2017-06-05)+----------------++### New features++* Add settings to be able to change the character used to deliminate control statements #18++### Document updates++* Fixed small spelling/grammars on readme #19+ Version 1.0.4.0 (2017-02-07) ---------------- 
README.md view
@@ -26,7 +26,7 @@ There are many Haskell template engines today. [Shakespeare](http://hackage.haskell.org/package/shakespeare) is great because it checks template variables at compile time.  Using Shakespeare, it's not-possible to for the template file to cause a runtime-error.+possible for the template file to cause a runtime-error.  Shakespeare provides its own original ways of writing HTML ([Hamlet](https://hackage.haskell.org/package/shakespeare/docs/Text-Hamlet.html)),@@ -53,7 +53,7 @@ [long time to compile](https://github.com/blueimpact/kucipong/pull/7) with GHC >= 7.10. -Hetercephalus fills this missing niche. It gives you variable interpolation+Heterocephalus fills this missing niche. It gives you variable interpolation along with control statements that can be used with any markup language.  Its compile times are reasonable. 
heterocephalus.cabal view
@@ -1,5 +1,5 @@ name:                heterocephalus-version:             1.0.4.0+version:             1.0.5.0 synopsis:            A type-safe template engine for working with popular front end development tools description:     Recent front end development tools and languages are growing fast and have@@ -33,15 +33,18 @@                      , Text.Heterocephalus.Parse                      , Text.Heterocephalus.Parse.Control                      , Text.Heterocephalus.Parse.Doc+                     , Text.Heterocephalus.Parse.Option   build-depends:       base >= 4.7 && < 5                      , blaze-html >= 0.8 && < 0.10                      , blaze-markup >= 0.7 && < 0.9                      , containers >= 0.5 && < 0.6                      , dlist >= 0.7.1.1+                     , mtl                      , parsec >= 3.1 && < 3.2                      , shakespeare >= 2.0 && < 2.1                      , template-haskell >= 2.7 && < 3                      , text >= 1.2 && < 1.3+                     , transformers   ghc-options:         -Wall   default-language:    Haskell2010 
src/Text/Heterocephalus.hs view
@@ -39,6 +39,9 @@   , HeterocephalusSetting(..)   , textSetting   , htmlSetting+  , ParseOptions(..)+  , defaultParseOptions+  , createParseOptions   , DefaultScope   , compile   , compileWith@@ -85,7 +88,8 @@        (Deref, Ident(..), Scope, derefToExp, readUtf8File)  import Text.Heterocephalus.Parse-       (Doc(..), Content(..), docFromString)+       (Doc(..), Content(..), ParseOptions(..), createParseOptions,+        defaultParseOptions, docFromString)  {- $setup   >>> :set -XTemplateHaskell -XQuasiQuotes@@ -332,6 +336,20 @@   contents <- fmap TL.unpack $ qRunIO $ readUtf8File fp   compileFromStringWithDefault scope' set contents +{-| Same as 'compileFile', but just compile the 'String' given.++  >>> let as = ["<a>", "b"]+  >>> let template = "sample %{ forall a <- as }key: #{a}, %{ endforall }"+  >>> renderMarkup $(compileFromString textSetting template)+  "sample key: <a>, key: b, "++  >>> let as = ["<a>", "b"]+  >>> let options = createParseOptions '|' '?'+  >>> let setting = textSetting { parseOptions = options }+  >>> let template = "sample |{ forall a <- as }key: ?{a}, |{ endforall }"+  >>> renderMarkup $(compileFromString setting template)+  "sample key: <a>, key: b, "+-} compileFromString :: HeterocephalusSetting -> String -> Q Exp compileFromString = compileFromStringWithDefault [] @@ -341,7 +359,7 @@     forM defScope $ \(ident, qexp) -> (ident, ) <$> overwriteScope ident qexp   owScope' <-     forM owScope $ \(ident, qexp) -> (ident, ) <$> qexp-  docsToExp set (owScope' ++ defScope') $ docFromString s+  docsToExp set (owScope' ++ defScope') $ docFromString (parseOptions set) s  where   (defDList, owDList) = runScopeM scopeM   defScope = DList.toList defDList@@ -351,7 +369,7 @@ compileFromStringWithDefault scope' set s = do   scope <-     forM scope' $ \(ident, qexp) -> (ident, ) <$> overwriteScope ident qexp-  docsToExp set scope $ docFromString s+  docsToExp set scope $ docFromString (parseOptions set) s  overwriteScope :: Ident -> Q Exp -> Q Exp overwriteScope (Ident str) qexp = do@@ -366,6 +384,7 @@   { escapeExp :: Q Exp   -- ^ Template variables are passed to 'escapeExp' in the output.  This allows   -- things like escaping HTML entities.  (See 'htmlSetting'.)+  , parseOptions :: ParseOptions   }  {-| A setting that escapes template variables for Html@@ -375,6 +394,7 @@ htmlSetting :: HeterocephalusSetting htmlSetting = HeterocephalusSetting   { escapeExp = [|toHtml|]+  , parseOptions = defaultParseOptions   }  {-| A setting that DOES NOT escape template variables.@@ -384,6 +404,7 @@ textSetting :: HeterocephalusSetting textSetting = HeterocephalusSetting   { escapeExp = [|preEscapedToMarkup|]+  , parseOptions = defaultParseOptions   }  type DefaultScope = [(Ident, Q Exp)]
src/Text/Heterocephalus/Parse.hs view
@@ -9,21 +9,24 @@   ( module Text.Heterocephalus.Parse   , module Text.Heterocephalus.Parse.Control   , module Text.Heterocephalus.Parse.Doc+  , module Text.Heterocephalus.Parse.Option   ) where  import Text.Heterocephalus.Parse.Control (Content(..), parseLineControl) import Text.Heterocephalus.Parse.Doc        (Doc(..), parseDocFromControls)+import Text.Heterocephalus.Parse.Option+       (ParseOptions(..), createParseOptions, defaultParseOptions) -docFromString :: String -> [Doc]-docFromString s =-  case parseDoc s of+docFromString :: ParseOptions -> String -> [Doc]+docFromString opts s =+  case parseDoc opts s of     Left s' -> error s'     Right d -> d -parseDoc :: String -> Either String [Doc]-parseDoc s = do-  controls <- parseLineControl s+parseDoc :: ParseOptions -> String -> Either String [Doc]+parseDoc opts s = do+  controls <- parseLineControl opts s   case parseDocFromControls controls of     Left parseError -> Left $ show parseError     Right docs -> Right docs
src/Text/Heterocephalus/Parse/Control.hs view
@@ -12,18 +12,23 @@ import Control.Applicative ((<$>), (*>), (<*), pure) #endif import Control.Monad (guard, void)+import Control.Monad.Reader (Reader, runReaderT) import Data.Char (isUpper) import Data.Data (Data) import Data.Functor (($>))+import Data.Functor.Identity (runIdentity) import Data.Typeable (Typeable) import Text.Parsec-       (Parsec, (<?>), (<|>), alphaNum, between, char, choice, eof, many,-        many1, manyTill, noneOf, oneOf, option, optional, parse, sepBy,-        skipMany, spaces, string, try)+       (Parsec, ParsecT, (<?>), (<|>), alphaNum, between, char, choice,+        eof, many, many1, manyTill, mkPT, noneOf, oneOf, option, optional,+        runParsecT, runParserT, sepBy, skipMany, spaces, string,+        try) import Text.Shakespeare.Base-       (Ident(Ident), Deref, parseDeref, parseHash)+       (Ident(Ident), Deref, parseDeref, parseVar)  import Text.Hamlet.Parse+import Text.Heterocephalus.Parse.Option+       (ParseOptions, getControlPrefix, getVariablePrefix)  data Control   = ControlForall Deref Binding@@ -42,52 +47,62 @@              | ContentVar Deref     deriving (Data, Eq, Read, Show, Typeable) -type UserParser = Parsec String ()+type UserParser = ParsecT String () (Reader ParseOptions) -parseLineControl :: String -> Either String [Control]-parseLineControl s =-  case parse lineControl s s of-    Left e -> Left $ show e-    Right x -> Right x+parseLineControl :: ParseOptions -> String -> Either String [Control]+parseLineControl opts s =+  let readerT = runParserT lineControl () "" s+      res = runIdentity $ runReaderT readerT opts+  in case res of+       Left e -> Left $ show e+       Right x -> Right x  lineControl :: UserParser [Control] lineControl = manyTill control $ try eof >> return ()  control :: UserParser Control-control = controlHash <|> controlPercent <|> controlReg+control = noControlVariable <|> controlStatement <|> noControlRaw   where-    controlPercent :: UserParser Control-    controlPercent = do-      x <- parsePercent+    controlStatement :: UserParser Control+    controlStatement = do+      x <- parseControlStatement       case x of         Left str -> return (NoControl $ ContentRaw str)         Right ctrl -> return ctrl -    controlHash :: UserParser Control-    controlHash = do-      x <- parseHash+    noControlVariable :: UserParser Control+    noControlVariable = do+      variablePrefix <- getVariablePrefix+      x <- identityToReader $ parseVar variablePrefix       return . NoControl $         case x of           Left str -> ContentRaw str           Right deref -> ContentVar deref -    controlReg :: UserParser Control-    controlReg = (NoControl . ContentRaw) <$> many (noneOf "#%")+    noControlRaw :: UserParser Control+    noControlRaw = do+      controlPrefix <- getControlPrefix+      variablePrefix <- getVariablePrefix+      (NoControl . ContentRaw) <$>+        many (noneOf [controlPrefix, variablePrefix]) -parsePercent :: UserParser (Either String Control)-parsePercent = do-  a <- parseControl '%'+parseControlStatement :: UserParser (Either String Control)+parseControlStatement = do+  a <- parseControl   optional eol   return a  where   eol :: UserParser ()   eol = void (char '\n') <|> void (string "\r\n") -parseControl :: Char -> UserParser (Either String Control)-parseControl c = do-  _ <- char c-  let escape = char '\\' $> Left [c]-  escape <|> (Right <$> parseControlBetweenBrackets) <|> return (Left [c])+parseControl :: UserParser (Either String Control)+parseControl = do+  controlPrefix <- getControlPrefix+  void $ char controlPrefix+  let escape = char '\\' $> Left [controlPrefix]+  escape <|>+    (Right <$> parseControlBetweenBrackets) <|>+    return (Left [controlPrefix])  parseControlBetweenBrackets :: UserParser Control parseControlBetweenBrackets =@@ -112,10 +127,14 @@     parseEndForall = string "endforall" $> ControlEndForall      parseIf :: UserParser Control-    parseIf = string "if" *> spaces *> fmap ControlIf parseDeref+    parseIf =+      string "if" *> spaces *> fmap ControlIf (identityToReader parseDeref)      parseElseIf :: UserParser Control-    parseElseIf = string "elseif" *> spaces *> fmap ControlElseIf parseDeref+    parseElseIf =+      string "elseif" *>+      spaces *>+      fmap ControlElseIf (identityToReader parseDeref)      parseElse :: UserParser Control     parseElse = string "else" $> ControlElse@@ -124,7 +143,10 @@     parseEndIf = string "endif" $> ControlEndIf      parseCase :: UserParser Control-    parseCase = string "case" *> spaces *> fmap ControlCase parseDeref+    parseCase =+      string "case" *>+      spaces *>+      fmap ControlCase (identityToReader parseDeref)      parseCaseOf :: UserParser Control     parseCaseOf = string "of" *> spaces *> fmap ControlCaseOf identPattern@@ -138,7 +160,7 @@       spaces       _ <- string "<-"       spaces-      x <- parseDeref+      x <- identityToReader parseDeref       _ <- spaceTabs       return (x, y) @@ -319,3 +341,7 @@          listpat :: UserParser Binding         listpat = BindList <$> identPattern `sepBy` comma++identityToReader :: Parsec String () a -> UserParser a+identityToReader p =+  mkPT $ pure . fmap (pure . runIdentity) . runIdentity . runParsecT p
+ src/Text/Heterocephalus/Parse/Option.hs view
@@ -0,0 +1,33 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}++module Text.Heterocephalus.Parse.Option where++import Control.Monad.Reader (MonadReader, reader)++data ParseOptions = ParseOptions+  { parseOptionsControlPrefix :: Char+  , parseOptionsVariablePrefix :: Char+  }++-- | Default set of parser options.+--+-- Sets 'parseOptionsControlPrefix' to @\'%\'@  and+-- 'parseOptionsVariablePrefix' to @\'#\'@.+defaultParseOptions :: ParseOptions+defaultParseOptions = createParseOptions '%' '#'++createParseOptions+  :: Char  -- ^ The control prefix.+  -> Char  -- ^ The variable prefix.+  -> ParseOptions+createParseOptions controlPrefix varPrefix = ParseOptions+  { parseOptionsControlPrefix = controlPrefix+  , parseOptionsVariablePrefix = varPrefix+  }++getControlPrefix :: MonadReader ParseOptions m => m Char+getControlPrefix = reader parseOptionsControlPrefix++getVariablePrefix :: MonadReader ParseOptions m => m Char+getVariablePrefix = reader parseOptionsVariablePrefix