packages feed

reflex-dom-th 0.1.0.0 → 0.2.0.0

raw patch · 5 files changed

+117/−72 lines, 5 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Reflex.Dom.TH: merge :: Ord a => [a] -> [a] -> [a]
+ Reflex.Dom.TH: instance GHC.Show.Show Reflex.Dom.TH.Chain
+ Reflex.Dom.TH: instance GHC.Show.Show Reflex.Dom.TH.ChildResult
- Reflex.Dom.TH.Parser: TWidget :: String -> TElement
+ Reflex.Dom.TH.Parser: TWidget :: String -> Maybe Ref -> TElement

Files

CHANGELOG.md view
@@ -1,5 +1,14 @@ # Revision history for reflex-dom-th -## 0.1.0.0 -- YYYY-mm-dd+## 0.2.0.0 -- 2022-02-18++* specialization to el-variants+* parse widgets inside texts+* allow refs to widgets+* dash '-' is now valid in attribute names+	+++## 0.1.0.0 -- 2022-02-18  * First version. Released on an unsuspecting world.
README.md view
@@ -8,37 +8,51 @@  The basic example -    [dom|<div>hello</div>|]+```+[dom|<div>hello</div>|]+```  is equivalent to -    el "div" $ text "hello"+```+el "div" $ text "hello"+```  You can also put the html in a external file and include it with -    $(domFile "template.html")+```+$(domFile "template.html")+```  It it possible to have multiple elements and attributes -    [dom|<ul class="list">-          <li>Item1</div>-	  <li>Item1</div>-	</ul> |]+```+[dom|<ul class="list">+       <li>Item1</div>+       <li>Item1</div>+     </ul> |]+```      -Dynamic content can be injected two curly braces+Dynamic content can be injected between two curly braces. It will reference an unbound variable. It is not a haskell expression. Keeping haskell out of the template will give you better error messages. -        [dom|<ul class="list">-          <li>{{item1}}</div>-	  <li>{{item2}}</div>-	</ul> |]-	   where item1, item2 :: MonadWidget t m =>  m ()-	         item1 = text "Item1"-		 item2 = text "Item2"+```+[dom|<ul class="list">+      <li>{{item1}}</div>+      <li>{{item2}}</div>+    </ul> |]+  where item1, item2 :: MonadWidget t m =>  m ()+        item1 = text "Item1"+        item2 = text "Item2"+```           To bind events to the elements it is possible to extract get the elements as a result. The reference number is the position in the result tuple. -    (li1, li2, ul) <- [dom|<ul #2 class="list">-    	       	             <li #0>Item1</div>-	  		     <li #1>Item1</div>-			   </ul> |]+```+(li1, li2, ul, w) <- [dom|<ul #2 class="list">+                           <li #0>Item1</div>+                           <li #1>Item1</div>+	                   <li>{{widget #3}}</div>+                          </ul> |]+```		       +
reflex-dom-th.cabal view
@@ -1,9 +1,9 @@ cabal-version:      2.4 name:               reflex-dom-th-version:            0.1.0.0+version:            0.2.0.0  -- A short (one-line) description of the package.-synopsis: reflex-dom-th transpiles HTML templates to haskell code for @reflex-dom@+synopsis: reflex-dom-th transpiles HTML templates to haskell code for reflex-dom  -- A longer description of the package. description:@@ -16,7 +16,7 @@ Stability: Experimental -- A URL where users can report bugs. bug-reports: https://github.com/chrbauer/reflex-dom-th/issues-+homepage:  https://github.com/chrbauer/reflex-dom-th license: BSD-3-Clause author:             Christoph Bauer maintainer:         mail@christoph-bauer.net
src/Reflex/Dom/TH.hs view
@@ -1,7 +1,7 @@ -- |   module Reflex.Dom.TH-  (dom, domFile, merge)+  (dom, domFile) where  @@ -14,24 +14,30 @@ import Reflex.Dom.TH.Parser import Reflex.Dom.Widget.Basic  import qualified Data.Map as M-import Data.Map (Map)---import Data.Maybe import Data.List (insert)-import Data.Text (Text)-import qualified Data.Text as T import Data.Array  type Ref = Int++data ChildResult =+   CREmpty+ | CRSimple Ref+ | CRTuple (Maybe Ref) [Ref]+ deriving Show++data Chain = CBind CElement ChildResult Chain | CResult [Ref]+  deriving Show+ data CElement = CElement { cTag :: String                          , cSiblingsRefs :: [Ref]                          , cChildRefs :: [Ref]                          , cOutRefs :: [Ref]                          , cMyRef :: Maybe Ref                          , cAttrs :: [(String, String)]-                         , cChilds :: [CElement] }+                         , cChilds :: Chain }                | CText String                | CComment String-               | CWidget String+               | CWidget String (Maybe Ref)                deriving Show  merge :: Ord a => [a] -> [a] -> [a]@@ -42,61 +48,72 @@   | otherwise = ah : merge at b  ---  do (r1, (r1a, r1b)) <- el1 $ el1a >>= \ r1a -> el1b >>= \r1b -> return (r1a, r1b)----compile :: [TElement] -> [CElement] -> [Ref] -> ([CElement], [Ref])-compile [] acc inRefs = (reverse acc, inRefs)-compile ((TElement {..}):etail) acc inRefs =-      compile etail (elem':acc) expRefs+compile :: [TElement] -> [Ref] -> Chain+compile [] inRefs = CResult inRefs+compile ((TElement {..}):etail) inRefs =+      CBind elem' (CRTuple tRef childRefs) (compile etail expRefs)   where-    elem' = CElement tTag inRefs childRefs outRefs tRef attrs childs-    (childs, childRefs) = compile tChilds [] []-    outRefs = maybe id insert tRef childRefs+    elem' = CElement tTag inRefs childRefs outRefs tRef attrs childChain+    childChain = compile tChilds []+    childRefs = chainOut childChain+    outRefs = maybe id insert tRef childRefs      expRefs = merge inRefs outRefs     attrs = [ (k, v) | (Static, k, v) <- tAttrs ]-compile (elem:etail) acc inRefs =-      compile etail (toC elem : acc) inRefs++compile (TWidget w r:etail)  inRefs =   CBind (CWidget w r) (maybe CREmpty CRSimple r) (compile etail expRefs)+    where expRefs = maybe id insert r inRefs+compile (e:etail) inRefs =+      CBind (toC e) CREmpty (compile etail inRefs)   where-    toC (TText text) = CText text-    toC (TComment comment) = CComment comment-    toC (TWidget widget) = CWidget widget-    toC _ = undefined+    toC (TText t) = CText t+    toC (TComment c) = CComment c+    toC _ = error "internal"                               opt :: (Ref -> Name) -> Maybe Ref -> Q Pat opt var = maybe (runQ [p| () |]) $ varP . var -clambda var Nothing crefs   =  lamE [tupP $ map (varP . var) crefs ]-clambda var mref crefs =  lamE [tupP [ opt var mref-                           , tupP $ map (varP . var) crefs]]+clambda :: (Ref -> Name) -> ChildResult -> ExpQ -> ExpQ+clambda _    CREmpty       =  lamE [wildP]+clambda var (CRSimple v)  =  lamE [tupP [varP $ var v]]+clambda var (CRTuple Nothing crefs)  =  lamE [tupP $ map (varP . var) crefs]+clambda var (CRTuple mref crefs)  =  lamE [tupP [ opt var mref+                                                , tupP $ map (varP . var) crefs]]+elWithAttr :: String -> [(String, String)] -> ExpQ+elWithAttr tag [] = [| el tag |]+elWithAttr tag [("class", cl)] = [| elClass tag cl |]+elWithAttr tag attr = [| elAttr tag (M.fromList attr) |] +el'WithAttr :: String -> [(String, String)] -> ExpQ+el'WithAttr tag [] = [| el' tag |]+el'WithAttr tag [("class", cl)] = [| elClass' tag cl |]+el'WithAttr tag attr = [| elAttr' tag (M.fromList attr) |] -cnodes :: (Ref -> Name) -> [CElement] ->  ExpQ-cnodes _ []  = [| blank |]-cnodes var [elem@(CElement _ _ crefs orefs mref _ _)]  -    | null orefs = [| $(cnode var elem) |]-    | otherwise = [| $(cnode var elem) >>=  $(clambda var mref crefs                                                                                        (appE (varE 'return) (tupE $ map (varE . var) orefs))) |]-cnodes var (elem@(CElement _ _ crefs orefs mref _ _):rest)  = [| $(cnode var elem) >>=  $(clambda var mref crefs (cnodes var rest)) |]-                                                         -cnodes  var [elem] = cnode var elem-cnodes var (h:t)  = [|  $(cnode var h) >> $(cnodes var t) |] +cchain :: (Ref -> Name) -> Chain ->  ExpQ+cchain var (CResult orefs)  = (appE (varE 'return) (tupE $ map (varE . var) orefs))+cchain var (CBind ce cres rest)  = [| $(cnode var ce) >>=  $(clambda var cres (cchain var rest)) |]+ cnode :: (Ref -> Name) -> CElement -> ExpQ-cnode var (CElement tag _ _ _ Nothing attr childs) = [|  elAttr tag (M.fromList attr) $(cnodes var childs)|]-cnode var (CElement tag _ _ _ (Just _) attr childs) = [|  elAttr' tag (M.fromList attr) $(cnodes var childs) |]+cnode var (CElement tag _ _ _ Nothing attr childs) = [|  $(elWithAttr tag attr) $(cchain var childs)|]+cnode var (CElement tag _ _ _ (Just _) attr childs) = [| $(el'WithAttr tag attr) $(cchain var childs) |] cnode _ (CText "") = [| blank |] cnode _ (CText txt) = [| text txt |]-cnode _ (CWidget x) = unboundVarE $ mkName x+cnode _ (CWidget x _) = unboundVarE $ mkName x cnode _ (CComment txt) = [| comment txt |] +chainOut :: Chain -> [Ref] +chainOut (CBind _ _ next) = chainOut next+chainOut (CResult out) = out+ domExp :: [TElement] -> Q Exp domExp result =-  let (cns, out) = compile result [] [] in do+  let refchain = compile result []+      out = chainOut refchain+  in do     varNames <-  listArray (0, length out) <$> mapM (\ r -> newName ("r" ++ show r)) out-    cnodes (varNames !) cns+    cchain (varNames !) refchain  dom :: QuasiQuoter dom = QuasiQuoter
src/Reflex/Dom/TH/Parser.hs view
@@ -29,24 +29,27 @@                          , tChilds :: [TElement] }                | TText String                | TComment String-               | TWidget String+               | TWidget String (Maybe Ref)                deriving Show +refOpt :: Parser (Maybe Int)+refOpt = optional . try $ do+      space1+      void $ char '#'+      L.decimal <* space  openTag :: Parser (String, Maybe Int, [Attribute]) openTag =        between (char '<') (char '>') $ do        tag <- many (alphaNumChar <|> char '-')+       ref <- refOpt        space-       ref <-  optional $ do-         void $ char '#'-         L.decimal <* space        attrs <- attributes        space        return (tag, ref, attrs)  closeTag :: String -> Parser ()-closeTag tag = void $ between (string "</") (space >> char '>') (string tag)+closeTag tag = void $ between (string "</" >> space) (char '>') (string tag >> space)  comment :: Parser TElement comment = TComment <$> ((string "<!--") *> (manyTill anySingle (string "-->")))@@ -56,7 +59,7 @@ stringLiteral = char '\"' *> manyTill L.charLiteral (char '\"')  attribute :: Parser Attribute-attribute = (Static,,) <$>  (some alphaNumChar <* char '=') <*> stringLiteral+attribute = (Static,,) <$>  (some (alphaNumChar <|> char '-') <* char '=') <*> stringLiteral   attributes :: Parser [Attribute]@@ -70,12 +73,14 @@   childs <- manyTill element (closeTag tag)   return $ TElement tag ref attrs childs +varName :: Parser String+varName = (:) <$> lowerChar <*> many alphaNumChar  widget :: Parser TElement-widget =  TWidget <$> (string "{{" *> manyTill anySingle (string "}}"))+widget =  TWidget <$> (string "{{" *> space *> varName) <*> (refOpt <* (string "}}"))  text :: Parser TElement-text =  TText <$>  dropWhileEnd isSpace <$> some (satisfy (/= '<'))+text =  TText <$>  dropWhileEnd isSpace <$>  someTill anySingle (lookAhead (char '<' *> return () <|> string "{{" *> return () ))  element :: Parser TElement      element = (comment <|>  node <|> widget <|> text) <* space