packages feed

plzwrk 0.0.0.8 → 0.0.0.9

raw patch · 19 files changed

+1408/−2266 lines, 19 filesdep −neat-interpolationPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies removed: neat-interpolation

API changes (from Hackage documentation)

- Web.Framework.Plzwrk: Browserful :: (jsval -> IO (Maybe [jsval])) -> (jsval -> IO (Maybe Bool)) -> (jsval -> IO (Maybe ByteString)) -> (jsval -> IO (Maybe Double)) -> (jsval -> IO (Maybe Int)) -> (jsval -> IO (Maybe String)) -> (jsval -> IO ()) -> RequestInit jsval -> IO jsval -> (String -> IO jsval) -> (String -> IO jsval) -> (String -> IO (Maybe jsval)) -> IO jsval -> (String -> RequestInit jsval -> IO jsval) -> (jsval -> String -> IO (Maybe jsval)) -> (jsval -> String -> IO jsval) -> (jsval -> String -> jsval -> IO jsval) -> (jsval -> String -> jsval -> jsval -> IO jsval) -> ([jsval] -> IO jsval) -> (Bool -> IO jsval) -> (ByteString -> IO jsval) -> (Double -> IO jsval) -> (Int -> IO jsval) -> (String -> IO jsval) -> IO jsval -> IO Double -> (jsval -> String -> jsval -> IO ()) -> (jsval -> IO ()) -> ((jsval -> IO ()) -> IO jsval) -> Browserful jsval
- Web.Framework.Plzwrk: [_makeHaskellCallback] :: Browserful jsval -> (jsval -> IO ()) -> IO jsval
- Web.Framework.Plzwrk: data Browserful jsval
- Web.Framework.Plzwrk.MockJSVal: MockJSFunction :: Int -> (MockJSVal -> IO ()) -> [LogEvent] -> MockJSVal
- Web.Framework.Plzwrk.Tag: _datalist :: AFSig s opq
- Web.Framework.Plzwrk.Tag: _datalist' :: Sig s opq
- Web.Framework.Plzwrk.Tag: _datalist'_ :: Sig_ s opq
- Web.Framework.Plzwrk.Tag: _datalist'__ :: Sig__ s opq
- Web.Framework.Plzwrk.Tag: _datalist_ :: AFSig_ s opq
- Web.Framework.Plzwrk.Tag: _datalist__ :: AFSig__ s opq
+ Web.Framework.Plzwrk: JSEnv :: (jsval -> IO (Maybe [jsval])) -> (jsval -> IO (Maybe Bool)) -> (jsval -> IO (Maybe ByteString)) -> (jsval -> IO (Maybe Double)) -> (jsval -> IO (Maybe Int)) -> (jsval -> IO (Maybe String)) -> (jsval -> IO ()) -> RequestInit jsval -> IO jsval -> (String -> IO jsval) -> (String -> IO jsval) -> (String -> IO (Maybe jsval)) -> IO jsval -> (String -> RequestInit jsval -> IO jsval) -> (jsval -> String -> IO (Maybe jsval)) -> (jsval -> String -> IO jsval) -> (jsval -> String -> jsval -> IO jsval) -> (jsval -> String -> jsval -> jsval -> IO jsval) -> ([jsval] -> IO jsval) -> (Bool -> IO jsval) -> (ByteString -> IO jsval) -> (Double -> IO jsval) -> (Int -> IO jsval) -> (String -> IO jsval) -> IO jsval -> IO Double -> (jsval -> String -> jsval -> IO ()) -> (jsval -> IO ()) -> ((jsval -> IO ()) -> IO jsval) -> ((jsval -> jsval -> IO ()) -> IO jsval) -> ((jsval -> jsval -> jsval -> IO ()) -> IO jsval) -> JSEnv jsval
+ Web.Framework.Plzwrk: [_makeHaskellCallback1] :: JSEnv jsval -> (jsval -> IO ()) -> IO jsval
+ Web.Framework.Plzwrk: [_makeHaskellCallback2] :: JSEnv jsval -> (jsval -> jsval -> IO ()) -> IO jsval
+ Web.Framework.Plzwrk: [_makeHaskellCallback3] :: JSEnv jsval -> (jsval -> jsval -> jsval -> IO ()) -> IO jsval
+ Web.Framework.Plzwrk: data JSEnv jsval
+ Web.Framework.Plzwrk.MockJSVal: MockJSFunction1 :: Int -> (MockJSVal -> IO ()) -> [LogEvent] -> MockJSVal
+ Web.Framework.Plzwrk.MockJSVal: MockJSFunction2 :: Int -> (MockJSVal -> MockJSVal -> IO ()) -> [LogEvent] -> MockJSVal
+ Web.Framework.Plzwrk.MockJSVal: MockJSFunction3 :: Int -> (MockJSVal -> MockJSVal -> MockJSVal -> IO ()) -> [LogEvent] -> MockJSVal
+ Web.Framework.Plzwrk.Tag: datalist :: AFSig s opq
+ Web.Framework.Plzwrk.Tag: datalist' :: Sig s opq
+ Web.Framework.Plzwrk.Tag: datalist'_ :: Sig_ s opq
+ Web.Framework.Plzwrk.Tag: datalist'__ :: Sig__ s opq
+ Web.Framework.Plzwrk.Tag: datalist_ :: AFSig_ s opq
+ Web.Framework.Plzwrk.Tag: datalist__ :: AFSig__ s opq
- Web.Framework.Plzwrk: [_freeCallback] :: Browserful jsval -> jsval -> IO ()
+ Web.Framework.Plzwrk: [_freeCallback] :: JSEnv jsval -> jsval -> IO ()
- Web.Framework.Plzwrk: [castToArray] :: Browserful jsval -> jsval -> IO (Maybe [jsval])
+ Web.Framework.Plzwrk: [castToArray] :: JSEnv jsval -> jsval -> IO (Maybe [jsval])
- Web.Framework.Plzwrk: [castToBool] :: Browserful jsval -> jsval -> IO (Maybe Bool)
+ Web.Framework.Plzwrk: [castToBool] :: JSEnv jsval -> jsval -> IO (Maybe Bool)
- Web.Framework.Plzwrk: [castToByteString] :: Browserful jsval -> jsval -> IO (Maybe ByteString)
+ Web.Framework.Plzwrk: [castToByteString] :: JSEnv jsval -> jsval -> IO (Maybe ByteString)
- Web.Framework.Plzwrk: [castToDouble] :: Browserful jsval -> jsval -> IO (Maybe Double)
+ Web.Framework.Plzwrk: [castToDouble] :: JSEnv jsval -> jsval -> IO (Maybe Double)
- Web.Framework.Plzwrk: [castToInt] :: Browserful jsval -> jsval -> IO (Maybe Int)
+ Web.Framework.Plzwrk: [castToInt] :: JSEnv jsval -> jsval -> IO (Maybe Int)
- Web.Framework.Plzwrk: [castToString] :: Browserful jsval -> jsval -> IO (Maybe String)
+ Web.Framework.Plzwrk: [castToString] :: JSEnv jsval -> jsval -> IO (Maybe String)
- Web.Framework.Plzwrk: [consoleLog] :: Browserful jsval -> jsval -> IO ()
+ Web.Framework.Plzwrk: [consoleLog] :: JSEnv jsval -> jsval -> IO ()
- Web.Framework.Plzwrk: [defaultRequestInit] :: Browserful jsval -> RequestInit jsval
+ Web.Framework.Plzwrk: [defaultRequestInit] :: JSEnv jsval -> RequestInit jsval
- Web.Framework.Plzwrk: [documentBody] :: Browserful jsval -> IO jsval
+ Web.Framework.Plzwrk: [documentBody] :: JSEnv jsval -> IO jsval
- Web.Framework.Plzwrk: [documentCreateElement] :: Browserful jsval -> String -> IO jsval
+ Web.Framework.Plzwrk: [documentCreateElement] :: JSEnv jsval -> String -> IO jsval
- Web.Framework.Plzwrk: [documentCreateTextNode] :: Browserful jsval -> String -> IO jsval
+ Web.Framework.Plzwrk: [documentCreateTextNode] :: JSEnv jsval -> String -> IO jsval
- Web.Framework.Plzwrk: [documentGetElementById] :: Browserful jsval -> String -> IO (Maybe jsval)
+ Web.Framework.Plzwrk: [documentGetElementById] :: JSEnv jsval -> String -> IO (Maybe jsval)
- Web.Framework.Plzwrk: [documentHead] :: Browserful jsval -> IO jsval
+ Web.Framework.Plzwrk: [documentHead] :: JSEnv jsval -> IO jsval
- Web.Framework.Plzwrk: [fetch] :: Browserful jsval -> String -> RequestInit jsval -> IO jsval
+ Web.Framework.Plzwrk: [fetch] :: JSEnv jsval -> String -> RequestInit jsval -> IO jsval
- Web.Framework.Plzwrk: [getPropertyAsOpaque] :: Browserful jsval -> jsval -> String -> IO (Maybe jsval)
+ Web.Framework.Plzwrk: [getPropertyAsOpaque] :: JSEnv jsval -> jsval -> String -> IO (Maybe jsval)
- Web.Framework.Plzwrk: [invokeOn0] :: Browserful jsval -> jsval -> String -> IO jsval
+ Web.Framework.Plzwrk: [invokeOn0] :: JSEnv jsval -> jsval -> String -> IO jsval
- Web.Framework.Plzwrk: [invokeOn1] :: Browserful jsval -> jsval -> String -> jsval -> IO jsval
+ Web.Framework.Plzwrk: [invokeOn1] :: JSEnv jsval -> jsval -> String -> jsval -> IO jsval
- Web.Framework.Plzwrk: [invokeOn2] :: Browserful jsval -> jsval -> String -> jsval -> jsval -> IO jsval
+ Web.Framework.Plzwrk: [invokeOn2] :: JSEnv jsval -> jsval -> String -> jsval -> jsval -> IO jsval
- Web.Framework.Plzwrk: [jsValFromArray] :: Browserful jsval -> [jsval] -> IO jsval
+ Web.Framework.Plzwrk: [jsValFromArray] :: JSEnv jsval -> [jsval] -> IO jsval
- Web.Framework.Plzwrk: [jsValFromBool] :: Browserful jsval -> Bool -> IO jsval
+ Web.Framework.Plzwrk: [jsValFromBool] :: JSEnv jsval -> Bool -> IO jsval
- Web.Framework.Plzwrk: [jsValFromByteString] :: Browserful jsval -> ByteString -> IO jsval
+ Web.Framework.Plzwrk: [jsValFromByteString] :: JSEnv jsval -> ByteString -> IO jsval
- Web.Framework.Plzwrk: [jsValFromDouble] :: Browserful jsval -> Double -> IO jsval
+ Web.Framework.Plzwrk: [jsValFromDouble] :: JSEnv jsval -> Double -> IO jsval
- Web.Framework.Plzwrk: [jsValFromInt] :: Browserful jsval -> Int -> IO jsval
+ Web.Framework.Plzwrk: [jsValFromInt] :: JSEnv jsval -> Int -> IO jsval
- Web.Framework.Plzwrk: [jsValFromString] :: Browserful jsval -> String -> IO jsval
+ Web.Framework.Plzwrk: [jsValFromString] :: JSEnv jsval -> String -> IO jsval
- Web.Framework.Plzwrk: [makeObject] :: Browserful jsval -> IO jsval
+ Web.Framework.Plzwrk: [makeObject] :: JSEnv jsval -> IO jsval
- Web.Framework.Plzwrk: [mathRandom] :: Browserful jsval -> IO Double
+ Web.Framework.Plzwrk: [mathRandom] :: JSEnv jsval -> IO Double
- Web.Framework.Plzwrk: [setValue] :: Browserful jsval -> jsval -> String -> jsval -> IO ()
+ Web.Framework.Plzwrk: [setValue] :: JSEnv jsval -> jsval -> String -> jsval -> IO ()
- Web.Framework.Plzwrk: consoleLogS :: Browserful jsval -> String -> IO ()
+ Web.Framework.Plzwrk: consoleLogS :: JSEnv jsval -> String -> IO ()
- Web.Framework.Plzwrk: elementSetAttribute :: Browserful jsval -> jsval -> String -> String -> IO ()
+ Web.Framework.Plzwrk: elementSetAttribute :: JSEnv jsval -> jsval -> String -> String -> IO ()
- Web.Framework.Plzwrk: elementTagName :: Browserful jsval -> jsval -> IO (Maybe String)
+ Web.Framework.Plzwrk: elementTagName :: JSEnv jsval -> jsval -> IO (Maybe String)
- Web.Framework.Plzwrk: eventPreventDefault :: Browserful jsval -> jsval -> IO ()
+ Web.Framework.Plzwrk: eventPreventDefault :: JSEnv jsval -> jsval -> IO ()
- Web.Framework.Plzwrk: eventTargetAddEventListener :: Browserful jsval -> jsval -> String -> jsval -> IO ()
+ Web.Framework.Plzwrk: eventTargetAddEventListener :: JSEnv jsval -> jsval -> String -> jsval -> IO ()
- Web.Framework.Plzwrk: eventTargetBlur :: Browserful jsval -> jsval -> IO ()
+ Web.Framework.Plzwrk: eventTargetBlur :: JSEnv jsval -> jsval -> IO ()
- Web.Framework.Plzwrk: eventTargetRemoveEventListener :: Browserful jsval -> jsval -> String -> jsval -> IO ()
+ Web.Framework.Plzwrk: eventTargetRemoveEventListener :: JSEnv jsval -> jsval -> String -> jsval -> IO ()
- Web.Framework.Plzwrk: eventTargetValue :: Browserful jsval -> jsval -> IO (Maybe String)
+ Web.Framework.Plzwrk: eventTargetValue :: JSEnv jsval -> jsval -> IO (Maybe String)
- Web.Framework.Plzwrk: getPropertyAsBool :: Browserful jsval -> jsval -> String -> IO (Maybe Bool)
+ Web.Framework.Plzwrk: getPropertyAsBool :: JSEnv jsval -> jsval -> String -> IO (Maybe Bool)
- Web.Framework.Plzwrk: getPropertyAsDouble :: Browserful jsval -> jsval -> String -> IO (Maybe Double)
+ Web.Framework.Plzwrk: getPropertyAsDouble :: JSEnv jsval -> jsval -> String -> IO (Maybe Double)
- Web.Framework.Plzwrk: getPropertyAsInt :: Browserful jsval -> jsval -> String -> IO (Maybe Int)
+ Web.Framework.Plzwrk: getPropertyAsInt :: JSEnv jsval -> jsval -> String -> IO (Maybe Int)
- Web.Framework.Plzwrk: getPropertyAsString :: Browserful jsval -> jsval -> String -> IO (Maybe String)
+ Web.Framework.Plzwrk: getPropertyAsString :: JSEnv jsval -> jsval -> String -> IO (Maybe String)
- Web.Framework.Plzwrk: htmlElemenetClick :: Browserful jsval -> jsval -> IO ()
+ Web.Framework.Plzwrk: htmlElemenetClick :: JSEnv jsval -> jsval -> IO ()
- Web.Framework.Plzwrk: nodeAppendChild :: Browserful jsval -> jsval -> jsval -> IO ()
+ Web.Framework.Plzwrk: nodeAppendChild :: JSEnv jsval -> jsval -> jsval -> IO ()
- Web.Framework.Plzwrk: nodeChildNodes :: Browserful jsval -> jsval -> IO (Maybe [jsval])
+ Web.Framework.Plzwrk: nodeChildNodes :: JSEnv jsval -> jsval -> IO (Maybe [jsval])
- Web.Framework.Plzwrk: nodeInsertBefore :: Browserful jsval -> jsval -> jsval -> jsval -> IO ()
+ Web.Framework.Plzwrk: nodeInsertBefore :: JSEnv jsval -> jsval -> jsval -> jsval -> IO ()
- Web.Framework.Plzwrk: nodeRemoveChild :: Browserful jsval -> jsval -> jsval -> IO ()
+ Web.Framework.Plzwrk: nodeRemoveChild :: JSEnv jsval -> jsval -> jsval -> IO ()
- Web.Framework.Plzwrk: nodeTextContent :: Browserful jsval -> jsval -> IO (Maybe String)
+ Web.Framework.Plzwrk: nodeTextContent :: JSEnv jsval -> jsval -> IO (Maybe String)
- Web.Framework.Plzwrk: plzwrk :: (state -> PwNode state jsval) -> state -> Browserful jsval -> String -> IO ()
+ Web.Framework.Plzwrk: plzwrk :: (state -> PwNode state jsval) -> state -> JSEnv jsval -> String -> IO ()
- Web.Framework.Plzwrk: plzwrk' :: (state -> PwNode state jsval) -> state -> Browserful jsval -> IO ()
+ Web.Framework.Plzwrk: plzwrk' :: (state -> PwNode state jsval) -> state -> JSEnv jsval -> IO ()
- Web.Framework.Plzwrk: plzwrk'_ :: (() -> PwNode () jsval) -> Browserful jsval -> IO ()
+ Web.Framework.Plzwrk: plzwrk'_ :: (() -> PwNode () jsval) -> JSEnv jsval -> IO ()
- Web.Framework.Plzwrk: plzwrkSSR :: (state -> PwNode state jsval) -> state -> Browserful jsval -> String -> IO ()
+ Web.Framework.Plzwrk: plzwrkSSR :: (state -> PwNode state jsval) -> state -> JSEnv jsval -> String -> IO ()
- Web.Framework.Plzwrk.MockJSVal: makeMockBrowser :: IO (Browserful Int)
+ Web.Framework.Plzwrk.MockJSVal: makeMockBrowser :: IO (JSEnv Int)
- Web.Framework.Plzwrk.MockJSVal: makeMockBrowserWithContext :: IORef MockBrowserInternal -> IO (Browserful Int)
+ Web.Framework.Plzwrk.MockJSVal: makeMockBrowserWithContext :: IORef MockBrowserInternal -> IO (JSEnv Int)

Files

ChangeLog.md view
@@ -1,5 +1,10 @@ # Changelog for plzwrk +## 0.0.0.9++- Renames `Browserful` to `JSEnv`.+- Fixes garbage collection bug for callback functions.+ ## 0.0.0.8  - Fixes a bug in the HSX parser that rejected certain valid text nodes
README.md view
@@ -24,24 +24,18 @@ 
 See it [live](https://plzwrk-kitchen-sink.surge.sh).
 
-## Installation
-
-Add `plzwrk` to the `build-depends` stanza of your `.cabal` file.
-
-Also, add `plzwrk-X.Y.Z.?` to the `extra-deps` list of your `stack.yaml` file if you're using stack.
-
 ## Making a webpage
 
-`plzwrk` uses [Asterius](https://github.com/tweag/asterius) as its backend for web development. Compiling an application using `plzwrk` is no different than compiling an application using `ahc-cabal` and `ahc-dist` as described in the [Asterius documentation](https://asterius.netlify.app) with **one caveat**. You **must** use `--constraint "plzwrk +plzwrk-enable-asterius"` when running `ahc-cabal`.
+`plzwrk` uses [Asterius](https://github.com/tweag/asterius) as its backend for web development. 
 
-A minimal flow is shown below, mostly copied from the asterius documentation. It assumes that you have a cabal-buildable project in the `pwd`. Note the use of the `--constraint "plzwrk +plzwrk-enable-asterius"` flag in the `ahc-cabal` step.
+A minimal flow is shown below. It assumes that you have a file called `Main.hs` in the present working directory with a function `main :: IO ()` inside of it, not unlike the Hello World above.
 
 ```bash
-username@hostname:~/my-dir$ docker run --rm -it -v $(pwd):/project -w /project terrorjack/asterius
-asterius@hostname:/project$ ahc-cabal v2-update
-asterius@hostname:/project$ ahc-cabal new-install --constraint "plzwrk +plzwrk-enable-asterius" --installdir <inst-dir> <exec-name>
-asterius@hostname:/project$ cd <inst-dir> && ahc-dist --input-exe <exec-name> --browser --bundle
+username@hostname:~/my-dir$ docker run --rm -it -v $(pwd):/project -w /project meeshkan/plzwrk
+asterius@hostname:/project$ ahc-link --input-hs Main.hs --browser --bundle
 ```
+
+If you're using `ahc-cabal`, compiling an application using `plzwrk` is no different than compiling an application as described in the [Asterius documentation](https://asterius.netlify.app) with **one caveat**. You **must** use `--constraint "plzwrk +plzwrk-enable-asterius"` when running `ahc-cabal`.
 
 ## Documentation
 
− hello-world/Main.hs
@@ -1,19 +0,0 @@-{-# LANGUAGE CPP               #-}
-{-# LANGUAGE QuasiQuotes       #-}
-
-import           Web.Framework.Plzwrk
-#if defined(PLZWRK_ENABLE_ASTERIUS)
-import           Web.Framework.Plzwrk.Asterius
-import           Web.Framework.Plzwrk.Tag (p__)
-#else
-import           Web.Framework.Plzwrk.MockJSVal
-#endif
-
-main :: IO ()
-main = do
-#if defined(PLZWRK_ENABLE_ASTERIUS)
-  browser <- asteriusBrowser
-# else
-  browser <- makeMockBrowser
-# endif
-  plzwrk'_ [hsx|<p>Hello world!</p>|] browser
− kitchen-sink/Main.hs
@@ -1,342 +0,0 @@-{-# LANGUAGE CPP               #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE QuasiQuotes #-}
-
-#if defined(PLZWRK_ENABLE_ASTERIUS)
-import           Asterius.Types
-import           Web.Framework.Plzwrk.Asterius
-# else
-import           Web.Framework.Plzwrk.MockJSVal
-# endif
-
-import           Control.Monad
-import           Data.HashMap.Strict     hiding ( null )
-import           Data.IORef
-import           NeatInterpolation
-import qualified Data.Set                      as S
-import qualified Data.Text                     as DT
-import           Nouns
-import           Prelude                 hiding ( div
-                                                , span
-                                                )
-import           Web.Framework.Plzwrk
-import           Web.Framework.Plzwrk.Tag
-                                         hiding ( main
-                                                , main_
-                                                , main'_
-                                                )
-import qualified Web.Framework.Plzwrk.Tag      as T
-                                                ( main
-                                                , main_
-                                                , main'_
-                                                )
-data MyState = MyState
-  { _name               :: String
-  , _abstractToConcrete :: [(String, String)]
-  , _myNoun             :: String
-  }
-  deriving Show
-
--- here is where we'll show our "surprise" aphorism
-surprise =
-  (\noun -> if (length noun == 0)
-      then div'_ []
-      else p'__ $ concat ["Life is like", indefiniteArticle noun, noun]
-    )
-    <$> _myNoun
-
--- here is where we will input a noun for our "surprise" aphorosim
-writeSomethingConcrete browser = input
-  [("type", pT "text"), ("style", pT "box-sizing:content-box"), ("input",
-    pF (\e s -> do
-      v <- (eventTargetValue browser) e
-      return $ maybe s (\q -> s { _myNoun = q }) v
-    )
-  )]
-  []
-
-aphorismList =
-  (\a2c -> ul'
-      [("class", pT "res")]
-      (fmap (\(a, c) -> (li__ (concat [a, " is like", indefiniteArticle c, c])))
-            a2c
-      )
-    )
-    <$> _abstractToConcrete
-
-addAphorismButton browser =
-  (\a2c -> button'
-      [("id", pT "incr"), ("class", pT "dim"), ("click",
-        pF (\e s -> do
-          (eventTargetBlur browser) e
-          (consoleLogS browser) $ "Here is the current state " <> show s
-          concept    <- randAbstract (mathRandom browser)
-          comparedTo <- randConcrete (mathRandom browser)
-          let newS = s { _abstractToConcrete = (concept, comparedTo) : a2c }
-          (consoleLogS browser) $ "Here is the new state " <> show newS
-          return $ newS
-        )
-      )]
-      [txt "More aphorisms"]
-    )
-    <$> _abstractToConcrete
-
-removeAphorismButton browser =
-  (\a2c -> button'
-      [("id", pT "decr"), ("class", pT "dim"), ("click", pF
-        (\e s -> do
-          (eventTargetBlur browser) e
-          pure $ s { _abstractToConcrete = if null a2c then [] else tail a2c }
-        )
-      )]
-      [txt "Less aphorisms"]
-    )
-    <$> _abstractToConcrete
-
-loginText =
-  (\name -> p'_ [txt "Logged in as: ", span [("class", pT "username")] [txt name]])
-    <$> _name
-
-main :: IO ()
-main = do
-
-#if defined(PLZWRK_ENABLE_ASTERIUS)
-  browser <- asteriusBrowser
-# else
-  browser <- makeMockBrowser
-# endif
-  -- add some css!
-  _head   <- (documentHead browser)
-  _style  <- (documentCreateElement browser) "style"
-  _css    <- (documentCreateTextNode browser) (DT.unpack myCss)
-  (nodeAppendChild browser) _style _css
-  (nodeAppendChild browser) _head _style
-  -- and here is our main div
-  let mainDivF = T.main_
-        [ section
-            [("class", pT "content")]
-            [ h1__ "Aphorism Machine"
-            , aphorismList
-            , br
-            , surprise
-            , div [("style", pT "width:100%;display:inline-block")]
-                  [addAphorismButton browser, removeAphorismButton browser]
-            , writeSomethingConcrete browser
-            , loginText
-            ]
-        ]
-  let state = MyState "Bob" [] ""
-  plzwrk' mainDivF state browser
-
-
-randFromList :: [String] -> IO Double -> IO String
-randFromList l f = do
-  z <- f
-  let i = round $ (fromIntegral $ length l) * z
-  return $ l !! i
-
-
-indefiniteArticle :: String -> String
-indefiniteArticle x =
-  let hd = take 1 x
-  in  if (hd == "a" || hd == "e" || hd == "i" || hd == "o" || hd == "u")
-        then " an "
-        else " a "
-
-randAbstract :: IO Double -> IO String
-randAbstract = randFromList abstract
-
-randConcrete :: IO Double -> IO String
-randConcrete = randFromList concrete
-
-myCss = [text|
-body {
-	margin: 0;
-	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
-	text-rendering: optimizeLegibility;
-	-webkit-font-smoothing: antialiased;
-}
-
-html,
-body {
-	height: 100%;
-}
-
-body>div:first-child,
-body>div:first-child>div:first-child,
-body>div:first-child>div:first-child>div {
-	height: inherit;
-}
-
-input {
-	box-sizing: border-box;
-	padding: 9.5px 15px;
-	border: 0;
-	text-align: center;
-	border-bottom: 1px solid #d8d8d8;
-	font-size: 14px;
-	transition: border-bottom-color 100ms ease-in, color 100ms ease-in;
-	max-width: 250px;
-	border-radius: 0;
-}
-
-input:focus {
-	outline: none;
-	border-color: #000;
-}
-
-.dim {
-    opacity: 1;
-    transition: opacity .15s ease-in;
-    cursor: pointer;
-}
-.dim:hover,
-.dim:focus {
-    opacity: .5;
-    transition: opacity .15s ease-in;
-}
-.dim:active {
-    opacity: .8;
-    transition: opacity .15s ease-out;
-}
-
-@media (min-width: 768px) {
-	input {
-		min-width: 300px;
-		max-width: 620px;
-	}
-}
-
-ul {
-    list-style: none;
-    padding-left: 0;
-}
-
-hr {
-    margin-top: 15px;
-    margin-bottom: 15px;
-    width: 70%;
-}
-
-main {
-	width: 100%;
-	height: 100%;
-	display: flex;
-	justify-content: center;
-	align-items: center;
-	padding: 20px;
-	box-sizing: border-box;
-	flex-direction: column;
-}
-
-.content {
-	text-align: center;
-	max-width: 100%;
-	-webkit-animation: fadein 2s;
-	-moz-animation: fadein 2s;
-	-ms-animation: fadein 2s;
-	-o-animation: fadein 2s;
-	animation: fadein 2s;
-}
-
-h1 {
-	font-family: 'Montserrat', sans-serif;
-	font-weight: normal;
-	font-size: 32px;
-	text-align: center;
-	margin-bottom: 25px;
-}
-
-aside {
-	display: flex;
-	justify-content: center;
-	align-items: center;
-	padding: 50px 0 40px 0;
-	position: absolute;
-	bottom: 0;
-	left: 0;
-	right: 0;
-}
-
-aside nav {
-	height: 18px;
-	display: flex;
-	justify-content: center;
-	align-items: center;
-}
-
-aside nav a {
-	font-size: 13px;
-	color: #b2b2b2;
-	text-decoration: none;
-	transition: color 100ms ease-in;
-}
-
-aside nav b {
-	display: block;
-	background: #b2b2b2;
-	width: 1px;
-	height: 100%;
-	margin: 0 10px;
-}
-
-.username {
-    font-weight: 500;
-}
-
-p {
-	font-weight: 400;
-	font-size: 14px;
-	line-height: 24px;
-	max-width: 390px;
-	text-align: center;
-	margin: 14px auto 30px auto;
-}
-
-button {
-    background-color: rgba(0, 0, 0, 0.671);
-    border: none;
-    color: white;
-    padding: 10px 12px;
-    margin: 10px;
-    text-align: center;
-    border-radius: 12px;
-    text-decoration: none;
-    display: inline-block;
-    font-size: 14px;
-  }
-
-@keyframes fadein {
-	from {
-		opacity: 0;
-	}
-	to {
-		opacity: 1;
-	}
-}
-
-@-moz-keyframes fadein {
-	from {
-		opacity: 0;
-	}
-	to {
-		opacity: 1;
-	}
-}
-
-@-webkit-keyframes fadein {
-	from {
-		opacity: 0;
-	}
-	to {
-		opacity: 1;
-	}
-}
-
-@media (max-height: 400px) {
-	aside {
-		display: none;
-	}
-}
-  |]
-
− kitchen-sink/Nouns.hs
@@ -1,519 +0,0 @@-module Nouns(abstract, concrete) where
-
-abstract =
-  [ "Ability"
-  , "Absurdity"
-  , "Achievement"
-  , "Action"
-  , "Adoration"
-  , "Adventure"
-  , "Advice"
-  , "Agitation"
-  , "Agony"
-  , "Alacrity"
-  , "Amazement"
-  , "Anger"
-  , "Anguish"
-  , "Anxiety"
-  , "Apathy"
-  , "Arrogance"
-  , "Artistry"
-  , "Audacity"
-  , "Awareness"
-  , "Awe"
-  , "Beauty"
-  , "Being"
-  , "Boredom"
-  , "Bravery"
-  , "Breadth"
-  , "Brilliance"
-  , "Brutality"
-  , "Calm"
-  , "Candor"
-  , "Care"
-  , "Chaos"
-  , "Charisma"
-  , "Charity"
-  , "Charm"
-  , "Childhood"
-  , "Clarity"
-  , "Cleverness"
-  , "Cohesion"
-  , "Coldness"
-  , "Comfort"
-  , "Communication"
-  , "Compassion"
-  , "Complexity"
-  , "Conceit"
-  , "Confidence"
-  , "Conflict"
-  , "Conformity"
-  , "Confusion"
-  , "Consciousness"
-  , "Control"
-  , "Courage"
-  , "Cowardice"
-  , "Crime"
-  , "Culture"
-  , "Dawn"
-  , "Day"
-  , "Death"
-  , "Deceit"
-  , "Defeat"
-  , "Delight"
-  , "Democracy"
-  , "Despair"
-  , "Disappointment"
-  , "Disbelief"
-  , "Discord"
-  , "Dishonesty"
-  , "Dissension"
-  , "Ego"
-  , "Elation"
-  , "Energy"
-  , "Ennui"
-  , "Enthusiasm"
-  , "Envy"
-  , "Evening"
-  , "Evil"
-  , "Excitement"
-  , "Exhilaration"
-  , "Exuberance"
-  , "Failure"
-  , "Faith"
-  , "Fear"
-  , "Fiction"
-  , "Forgiveness"
-  , "Freedom"
-  , "Genius"
-  , "Goodness"
-  , "Grace"
-  , "Greatness"
-  , "Grief"
-  , "Growth"
-  , "Happiness"
-  , "Hate"
-  , "Honesty"
-  , "Honor"
-  , "Hope"
-  , "Hubris"
-  , "Humility"
-  , "Humor"
-  , "Hunger"
-  , "Impudence"
-  , "Indifference"
-  , "Infatuation"
-  , "Insanity"
-  , "Integrity"
-  , "Intelligence"
-  , "Irritation"
-  , "Jealousy"
-  , "Joy"
-  , "Jubilation"
-  , "Justice"
-  , "Justification"
-  , "Kindness"
-  , "Kingship"
-  , "Knack"
-  , "Knell"
-  , "Knowledge"
-  , "Laughter"
-  , "Lavishness"
-  , "Law"
-  , "Leadership"
-  , "Leer"
-  , "Legitimacy"
-  , "Leisure"
-  , "Length"
-  , "Liberty"
-  , "Lie"
-  , "Life"
-  , "Listlessness"
-  , "Loneliness"
-  , "Loss"
-  , "Love"
-  , "Loyalty"
-  , "Luck"
-  , "Luxury"
-  , "Malice"
-  , "Maliciousness"
-  , "Malignity"
-  , "Manhood"
-  , "Marriage"
-  , "Martyrdom"
-  , "Maturity"
-  , "Meekness"
-  , "Membership"
-  , "Memory"
-  , "Mercy"
-  , "Meticulousness"
-  , "Mien"
-  , "Minute"
-  , "Misery"
-  , "Modesty"
-  , "Modicum"
-  , "Moment"
-  , "Monotony"
-  , "Month"
-  , "Morning"
-  , "Mortification"
-  , "Motivation"
-  , "Movement"
-  , "Movement"
-  , "Music"
-  , "Myriad"
-  , "Nadir"
-  , "Naivete"
-  , "Nap"
-  , "Narcissism"
-  , "Nausea"
-  , "Need"
-  , "Negativity"
-  , "Nervousness"
-  , ""
-  , "Newness"
-  , "Nonconformity"
-  , "Normalcy"
-  , "Nouns"
-  , "Nuance"
-  , "Obnoxiousness"
-  , "Occasion"
-  , "Omen"
-  , "Openness"
-  , "Opinion"
-  , "Opportunism"
-  , "Opportunity"
-  , "Optimism"
-  , "Pain"
-  , "Panacea"
-  , "Parenthood"
-  , "Parsimony"
-  , "Particularity"
-  , "Passiveness"
-  , "Past"
-  , "Patience"
-  , "Patriotism"
-  , "Peace"
-  , "Peculiar"
-  , "Peculiarity"
-  , "Penchant"
-  , "Permanence"
-  , "Permission"
-  , "Perseverance"
-  , "Perusal"
-  , "Pessimism"
-  , "Philosophy"
-  , "Placidity"
-  , "Pleasure"
-  , "Plethora"
-  , "Positivity"
-  , "Poverty"
-  , "Power"
-  , "Precision"
-  , "Predilection"
-  , "Preeminence"
-  , "Pride"
-  , "Principle"
-  , "Progress"
-  , "Prominence"
-  , "Prosperity"
-  , "Rage"
-  , "Reality"
-  , "Reason"
-  , "Redemption"
-  , "Refreshment"
-  , "Refusal"
-  , "Refutation"
-  , "Relaxation"
-  , "Relief"
-  , "Religion"
-  , "Reminiscence"
-  , "Repercussion"
-  , "Replacement"
-  , "Repulsiveness"
-  , "Resiliency"
-  , "Restoration"
-  , "Retirement"
-  , "Rhythm"
-  , "Riches"
-  , "Right"
-  , "Romance"
-  , "Rumor"
-  , "Rumour"
-  , "Ruthlessness"
-  , "Sacrifice"
-  , "Sadness"
-  , "Sale"
-  , "Sanity"
-  , "Satisfaction"
-  , "Scholarship"
-  , "Scrupulousness"
-  , "Security"
-  , "Self"
-  , "Sensitivity"
-  , "Serendipity"
-  , "Serenity"
-  , "Service"
-  , "Shock"
-  , "Silliness"
-  , "Sincerity"
-  , "Situation"
-  , "Skill"
-  , "Slave"
-  , "Slavery"
-  , "Sleep"
-  , "Solace"
-  , "Solitude"
-  , "Sophistication"
-  , "Sorrow"
-  , "Sparkle"
-  , "Speculation"
-  , "Speech"
-  , "Speed"
-  , "Spitefulness"
-  , "Squandering"
-  , "Stance"
-  , "Stardom"
-  , "States"
-  , "States"
-  , "Stinginess"
-  , "Strength"
-  , "Stress"
-  , "Strict"
-  , "Strictness"
-  , "Strife"
-  , "Stupidity"
-  , "Submission"
-  , "Success"
-  , "Suffering"
-  , "Surprise"
-  , "Susceptibleness"
-  , "Sympathy"
-  , "Talent"
-  , "Tediousness"
-  , "Tedium"
-  , "Tender"
-  , "Testimony"
-  , "Thirst"
-  , "Thoroughness"
-  , "Thought"
-  , "Thrill"
-  , "Time"
-  , "Timidness"
-  , "Timing"
-  , "Tired"
-  , "Tiredness"
-  , "Tolerance"
-  , "Torment"
-  , "Tranquility"
-  , "Treachery"
-  , "Treatment"
-  , "Trend"
-  , "Trouble"
-  , "Trust"
-  , "Truth"
-  , "Turbulence"
-  , "Turmoil"
-  , "Ubiquity"
-  , "Ugliness"
-  , "Umbrage"
-  , "Uncertainty"
-  , "Uncouthness"
-  , "Unease"
-  , "Unemployment"
-  , "Union"
-  , "Uniqueness"
-  , "Unreality"
-  , "Utility"
-  , "Vanity"
-  , "Viciousness"
-  , "Victory"
-  , "Vulnerability"
-  , "Wariness"
-  , "Warmth"
-  , "Wary"
-  , "Weakness"
-  , "Wealth"
-  , "Weariness"
-  , "Week"
-  , "Width"
-  , "Wisdom"
-  , "Wit"
-  ]
-
-concrete =
-  [ "whisker"
-  , "paw"
-  , "mammoth"
-  , "spider"
-  , "moth"
-  , "bug"
-  , "bat"
-  , "vulture"
-  , "owl"
-  , "turtle"
-  , "worm"
-  , "earthworm"
-  , "toad"
-  , "porcupine"
-  , "armadillo"
-  , "rat"
-  , "squirrel"
-  , "hedgehog"
-  , "chipmunk"
-  , "gerbil"
-  , "hamster"
-  , "mouse"
-  , "mole"
-  , "anteater"
-  , "platypus"
-  , "cow"
-  , "oxen"
-  , "cattle"
-  , "sheep"
-  , "lamb"
-  , "ram"
-  , "goat"
-  , "kid"
-  , "pig"
-  , "hog"
-  , "shoat"
-  , "sow"
-  , "fox"
-  , "vixen"
-  , "lemur"
-  , "raccoon"
-  , "weasel monkey"
-  , "ape"
-  , "chimpanzee"
-  , "orangutan"
-  , "baboon"
-  , "pony"
-  , "pinto"
-  , "mare"
-  , "filly"
-  , "gelding"
-  , "bronco"
-  , "colt"
-  , "stallion"
-  , "donkey"
-  , "zebra"
-  , "mule"
-  , "camel"
-  , "dromedary"
-  , "gazelle"
-  , "tom"
-  , "bird"
-  , "goose"
-  , "duck"
-  , "drake"
-  , "gander"
-  , "turkey"
-  , "songbird"
-  , "lark"
-  , "nightingale"
-  , "wren"
-  , "eagle"
-  , "hawk"
-  , "kitten"
-  , "chick"
-  , "rooster"
-  , "hen"
-  , "crow"
-  , "raven"
-  , "cat"
-  , "kitten"
-  , "mutt"
-  , "wolf"
-  , "cub"
-  , "tiger"
-  , "lion"
-  , "elephant"
-  , "cheetah"
-  , "puma"
-  , "jackal"
-  , "jaguar"
-  , "ocelot"
-  , "rhinoceros"
-  , "alpaca"
-  , "antelope"
-  , "deer"
-  , "doe"
-  , "fawn"
-  , "stag"
-  , "kangaroo"
-  , "joey"
-  , "koala"
-  , "sloth"
-  , "wombat"
-  , "bear"
-  , "hyena"
-  , "crocodile"
-  , "snake"
-  , "giraffe"
-  , "whale"
-  , "shark"
-  , "dolphin"
-  , "seal"
-  , "bed"
-  , "hammock"
-  , "hassock"
-  , "mirror"
-  , "hutch"
-  , "locker"
-  , "painting"
-  , "chalice"
-  , "cage"
-  , "urn"
-  , "bow"
-  , "sword"
-  , "dart"
-  , "dagger"
-  , "hatchet"
-  , "candle"
-  , "mop"
-  , "pail"
-  , "pipe"
-  , "brush"
-  , "easel"
-  , "gun"
-  , "rope"
-  , "balloon"
-  , "vase"
-  , "typewriter"
-  , "stylus"
-  , "pencil"
-  , "desk"
-  , "backpack"
-  , "saddle"
-  , "cash machine pot"
-  , "plate"
-  , "dish"
-  , "fork"
-  , "spoon"
-  , "samovar"
-  , "monsoon"
-  , "hurricane"
-  , "typhoon"
-  , "rain"
-  , "storm"
-  , "hail"
-  , "blizzard"
-  , "breeze"
-  , "whirlwind"
-  , "maelstrom"
-  , "dust storm"
-  , "cloudburst"
-  , "tornado"
-  , "twister"
-  , "cloud"
-  , "flood"
-  , "aftershock"
-  , "tremor"
-  , "earthquake"
-  , "lightning avalanche"
-  , "eclipse"
-  , "meteor shower"
-  , "thunderbolt"
-  , "tsunami"
-  ]
plzwrk.cabal view
@@ -7,7 +7,7 @@ -- hash: 8099ceb0d406f862d89306de053aba4c75999a9e0d74ac6a502458d503e7dcc1
 
 name:           plzwrk
-version:        0.0.0.8
+version:        0.0.0.9
 category:       Web
 synopsis:       A front-end framework
 description:    Please see the README on GitHub at <https://github.com/meeshkan/plzwrk#readme>
@@ -41,7 +41,7 @@   other-modules:
       Paths_plzwrk
     , Web.Framework.Plzwrk.Base
-    , Web.Framework.Plzwrk.Browserful
+    , Web.Framework.Plzwrk.JSEnv
     , Web.Framework.Plzwrk.Domify
     , Web.Framework.Plzwrk.Util
     , Web.Framework.Plzwrk.TH.HSX
@@ -68,43 +68,6 @@       -DPLZWRK_ENABLE_ASTERIUS
     build-depends:
       asterius-prelude
-
-executable kitchen-sink-exe
-  main-is: Main.hs
-  other-modules:
-      Nouns
-    , Paths_plzwrk
-  hs-source-dirs:
-      kitchen-sink
-  ghc-options: -rtsopts -with-rtsopts=-N
-  build-depends:
-      base >=4.7 && <5
-    , plzwrk
-    , containers >= 0.6.2 && < 0.7
-    , neat-interpolation >= 0.5.1 && < 0.6
-    , text >= 1.2.3 && < 1.3
-    , unordered-containers >= 0.2.10 && < 0.3
-    
-  default-language: Haskell2010
-  if flag(plzwrk-enable-asterius)
-    cpp-options:
-      -DPLZWRK_ENABLE_ASTERIUS
-
-executable hello-world-exe
-  main-is: Main.hs
-  other-modules:
-      Paths_plzwrk
-  hs-source-dirs:
-      hello-world
-  ghc-options: -rtsopts -with-rtsopts=-N
-  build-depends:
-      base >=4.7 && <5
-    , plzwrk
-    , text >= 1.2.3 && < 1.3
-  default-language: Haskell2010
-  if flag(plzwrk-enable-asterius)
-    cpp-options:
-      -DPLZWRK_ENABLE_ASTERIUS
 
 test-suite plzwrk-test
   type: exitcode-stdio-1.0
src/Web/Framework/Plzwrk.hs view
@@ -21,7 +21,7 @@   , toHTML
   , PwNode(..)
   , PwAttribute(..)
-  , Browserful(..)
+  , JSEnv(..)
   -- hsx
   , hsx
   , hsx'
@@ -54,7 +54,7 @@ 
 import           Prelude                 hiding ( div )
 import           Web.Framework.Plzwrk.Base
-import           Web.Framework.Plzwrk.Browserful
+import           Web.Framework.Plzwrk.JSEnv
 import           Web.Framework.Plzwrk.Domify
 import           Web.Framework.Plzwrk.Util
 import           Web.Framework.Plzwrk.TH.QuoteHSX
src/Web/Framework/Plzwrk/Asterius.hs view
@@ -29,10 +29,10 @@ import           Data.HashMap.Strict as HM
 import           Data.Coerce
 import           Foreign.Ptr
-import           Web.Framework.Plzwrk.Browserful
+import           Web.Framework.Plzwrk.JSEnv
 
-asteriusBrowser :: IO (Browserful JSVal)
-asteriusBrowser = return Browserful
+asteriusBrowser :: IO (JSEnv JSVal)
+asteriusBrowser = return JSEnv
   { 
     castToArray                    = _castToArray
   , castToBool                     = _castToBool
@@ -61,7 +61,9 @@   , setValue                       = _setValue
   , invokeOn1                      = _invokeOn1
   , invokeOn2                      = _invokeOn2
-  , _makeHaskellCallback           = __makeHaskellCallback
+  , _makeHaskellCallback1          = __makeHaskellCallback1
+  , _makeHaskellCallback2          = __makeHaskellCallback2
+  , _makeHaskellCallback3          = __makeHaskellCallback3
   , mathRandom                     = _mathRandom
   }
 
@@ -210,11 +212,21 @@ _setValue' :: JSVal -> String -> String -> IO ()
 _setValue' a b c = _js_setValue a (toJSString b) $ _s2v (toJSString c)
 
-__makeHaskellCallback :: (JSVal -> IO ()) -> IO JSVal
-__makeHaskellCallback a = do
+__makeHaskellCallback1 :: (JSVal -> IO ()) -> IO JSVal
+__makeHaskellCallback1 a = do
   x <- makeHaskellCallback1 a
   return $ getJSVal x
 
+__makeHaskellCallback2 :: (JSVal -> JSVal -> IO ()) -> IO JSVal
+__makeHaskellCallback2 a = do
+  x <- makeHaskellCallback2 a
+  return $ getJSVal x
+
+__makeHaskellCallback3 :: (JSVal -> JSVal -> JSVal -> IO ()) -> IO JSVal
+__makeHaskellCallback3 a = do
+  x <- makeHaskellCallback3 a
+  return $ getJSVal x
+
 __freeCallback :: JSVal -> IO ()
 __freeCallback v = freeHaskellCallback (JSFunction v)
 
@@ -282,8 +294,14 @@ foreign import javascript "document.getElementById($1)"
   js_documentGetElementById :: JSString -> IO JSVal
 
-foreign import javascript "wrapper oneshot"
+foreign import javascript "wrapper"
   makeHaskellCallback1 :: (JSVal -> IO ()) -> IO JSFunction
+
+foreign import javascript "wrapper"
+  makeHaskellCallback2 :: (JSVal -> JSVal -> IO ()) -> IO JSFunction
+
+foreign import javascript "wrapper"
+  makeHaskellCallback3 :: (JSVal -> JSVal -> JSVal -> IO ()) -> IO JSFunction
 
 # else
 module Web.Framework.Plzwrk.Asterius where
src/Web/Framework/Plzwrk/Base.hs view
@@ -15,9 +15,9 @@ import qualified Data.HashMap.Strict           as HM import qualified Data.Set                      as S -cssToStyle :: (HM.HashMap String String) -> String+cssToStyle :: HM.HashMap String String -> String cssToStyle css =-  (intercalate ";" $ fmap (\(x, y) -> x <> ":" <> y) (HM.toList css))+  intercalate ";" $ fmap (\(x, y) -> x <> ":" <> y) (HM.toList css)   -- |PwAttribute for a DOM PwNode.@@ -62,7 +62,7 @@  data PwNode s opq = PwElement     { _elt_tag :: String-    , _elt_attrs :: [(String, (s -> PwAttribute s opq))]+    , _elt_attrs :: [(String, s -> PwAttribute s opq)]     , _elt_children :: [s -> PwNode s opq]     } | PwTextNode { _tn_text :: String } @@ -80,7 +80,7 @@  _hydrate :: s -> PwNode s opq -> HydratedPwNode s opq _hydrate s (PwElement a b c) =-  HydratedPwElement a (fmap (\(x, y) -> (x, y s)) b) (fmap (\x -> hydrate s x) c)+  HydratedPwElement a (fmap (\(x, y) -> (x, y s)) b) (fmap (hydrate s) c) _hydrate s (PwTextNode t) = HydratedPwTextNode t  hydrate :: s -> (s -> PwNode s opq) -> HydratedPwNode s opq@@ -98,13 +98,13 @@ _toHTML (HydratedPwElement tag attrs ch) =   "<"     ++ tag-    ++ (if (null atts) then "" else " " ++ atts)-    ++ (if (null ch)+    ++ (if null atts then "" else " " ++ atts)+    ++ (if null ch          then "/>"-         else ">" ++ (concat $ fmap _toHTML ch) ++ "</" ++ tag ++ ">"+         else ">" ++ concatMap _toHTML ch ++ "</" ++ tag ++ ">"        )  where-  atts = intercalate " " $ fmap+  atts = unwords $ fmap     (\(x, y) -> x <> "=\"" <> stringifyPwAttribute y <> "\"")     (filter (isText . snd) attrs) _toHTML (HydratedPwTextNode txt) = txt
− src/Web/Framework/Plzwrk/Browserful.hs
@@ -1,131 +0,0 @@-module Web.Framework.Plzwrk.Browserful
-  ( Browserful(..)
-  , RequestInit(..)
-  , FetchBody(..)
-  )
-where
-
-import           Data.ByteString.Internal  ( ByteString )
-import qualified Data.HashMap.Strict      as HM
-
--- | A data class holding functions that operate on opaque
--- JavaScript types, parameterized by @jsval@. When possible,
--- the real names of browser functions like 'addEventListener'
--- and 'appendChild' are used.
---
--- Browserful is currently implemented as data instead of as
--- a typeclass because it is unclear what type of additional
--- monadic transformer around IO would be most appropriate to
--- retain the state of @jsval@ objects, whereas when part of
--- a dataclass, the state retention is abstracted away.
-
-data Browserful jsval = Browserful
-  {
-    -- | Casts a value to an array of jsvals
-    castToArray                  :: jsval -> IO (Maybe [jsval])
-
-    -- | Casts a value to a bool
-  , castToBool                    :: jsval -> IO (Maybe Bool)
-
-    -- | Casts a value to a bool
-  , castToByteString              :: jsval -> IO (Maybe ByteString)
-
-    -- | Casts a value to a double
-  , castToDouble                  :: jsval -> IO (Maybe Double)
-
-    -- | Casts a value to an int
-  , castToInt                     :: jsval -> IO (Maybe Int)
-
-    -- | Casts a value to a string
-  , castToString                  :: jsval -> IO (Maybe String)
-
-    -- | Logs an opaque JavaScript value. See [Console.log](https://developer.mozilla.org/en-US/docs/Web/API/Console/log)
-  , consoleLog                     :: jsval -> IO ()
-
-    -- | A default request init
-  , defaultRequestInit             :: RequestInit jsval
-
-    -- | The body of the document. See [Document.body](https://developer.mozilla.org/en-US/docs/Web/API/Document/body)
-  , documentBody                   :: IO jsval
-
-    -- | Creates an element with a given tag. See [Document.createElement](https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement)
-  , documentCreateElement          :: String -> IO jsval
-
-    -- | Creates a text node with the given text. See [Document.createTextNode](https://developer.mozilla.org/en-US/docs/Web/API/Document/createTextNode)
-  , documentCreateTextNode         :: String -> IO jsval
-
-    -- | Gets an element by id from a document. See [Document.getElementById](https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById)
-  , documentGetElementById         :: String -> IO (Maybe jsval)
-
-    -- | Gets the head of a document. See [Document.head](https://developer.mozilla.org/en-US/docs/Web/API/Document/head)
-  , documentHead                   :: IO jsval
-
-    -- | Calls the browser's fetch command
-  , fetch                          :: String -> (RequestInit jsval) -> IO jsval
-
-    -- | Gets a JavaScript property, returning @Nothing@ if the object being called is null or undefined.
-  , getPropertyAsOpaque            :: jsval -> String -> IO (Maybe jsval)
-
-    -- | Invokes on target a function with 0 arguments.
-  , invokeOn0                      :: jsval -> String -> IO jsval
-
-    -- | Invokes on target a function with 1 argument.
-  , invokeOn1                      :: jsval -> String -> jsval -> IO jsval
-
-    -- | Invokes on target a function with 2 arguments.
-  , invokeOn2                      :: jsval -> String -> jsval -> jsval -> IO jsval
-
-    -- | jsval from an array of jsvals
-  , jsValFromArray                 :: [jsval] -> IO jsval
-
-    -- | jsval from a bool
-  , jsValFromBool                  :: Bool -> IO jsval
-
-    -- | jsval from a byte string
-  , jsValFromByteString            :: ByteString -> IO jsval
-
-    -- | jsval from a double
-  , jsValFromDouble                :: Double -> IO jsval
-
-    -- | jsval from an int
-  , jsValFromInt                   :: Int -> IO jsval
-
-    -- | jsval from a string
-  , jsValFromString                :: String -> IO jsval
-
-    -- | Creates an object
-  , makeObject                     :: IO jsval
-
-    -- | Generate a random double between 0 and 1. See [Math.random](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random)
-  , mathRandom                     :: IO Double
-
-    -- | Sets on an object a value
-  , setValue                       :: jsval -> String -> jsval -> IO ()
-
-    -- | Frees a callback. Should only be called in advanced cases. In most usage, callbacks are freed automatically by plzwrk.
-  , _freeCallback                  :: jsval -> IO ()
-
-    -- | Makes a haskell callback. Should only be called in advanced cases. In most usage, callbacks are created automatically by plzwrk.
-  , _makeHaskellCallback           :: (jsval -> IO ()) -> IO jsval
-  }
-
--- |The body of a fetch request or response
-data FetchBody jsval =
-    FormDataBody (HM.HashMap String jsval) -- ^ From form data, ie @multipart/form-data@ or @application/x-www-form-urlencoded@
-  | StringBody   String -- ^ A string, ie @text/plain@ or @application/json@
-  | BlobBody     jsval -- ^ A single file
-  | URLSearchParamsBody (HM.HashMap String String) -- ^ Useful for @application/x-www-form-urlencoded@
-  | Uint8Array   ByteString
-
--- | Initialization parameters for a request made with fetch
-data RequestInit jsval = RequestInit {
-    _ri_method      :: Maybe String -- ^ The request method, e.g., GET, POST. The default is GET.
-  , _ri_headers     :: Maybe (HM.HashMap String String) -- ^ Any headers you want to add to your request, contained within a Headers object or an object literal with ByteString values.
-  , _ri_body        :: Maybe (FetchBody jsval) -- ^ Any body that you want to add to your request: this can be a Blob, BufferSource, FormData, URLSearchParams, USVString, or ReadableStream object. Note that a request using the GET or HEAD method cannot have a body.
-  , _ri_mode        :: Maybe String -- ^ The mode you want to use for the request, e.g., cors, no-cors, same-origin, or navigate. The default is cors.
-  , _ri_credentials :: Maybe String -- ^ The request credentials you want to use for the request: omit, same-origin, or include. The default is same-origin.
-  , _ri_cache       :: Maybe String -- ^ The cache mode you want to use for the request.
-  , _ri_redirect    :: Maybe String -- ^ The redirect mode to use: follow, error, or manual. The default is follow.
-  , _ri_referrer    :: Maybe String -- ^ A USVString specifying no-referrer, client, or a URL. The default is about:client.
-  , _ri_integrity   :: Maybe String -- ^ Contains the subresource integrity value of the request (e.g., sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=).
-}
src/Web/Framework/Plzwrk/Domify.hs view
@@ -1,524 +1,513 @@-module Web.Framework.Plzwrk.Domify-  ( plzwrk-  , plzwrk'-  , plzwrk'_-  , plzwrkSSR-  , plzwrkSSR'-  , plzwrkSSR'_-  )-where--import           Control.Applicative-import           Data.List.Split-import           Control.Monad-import           Control.Monad.Reader-import           Control.Monad.Trans-import           Control.Monad.Trans.Maybe-import qualified Data.HashMap.Strict           as HM-import           Data.IORef-import           Data.Maybe                     ( catMaybes )-import qualified Data.Set                      as S-import           Web.Framework.Plzwrk.Base-import           Web.Framework.Plzwrk.Browserful-import           Web.Framework.Plzwrk.Util--data DomifiedAttribute jsval = DomifiedTextAttribute String | DomifiedFunctionAttribute jsval--data DomifiedPwNode jsval = DomifiedPwElement-    { _dom_tag  :: String-    , _dom_attr :: [(String, DomifiedAttribute jsval)]-    , _dom_kids :: [DomifiedPwNode jsval]-    , _dom_ptr  :: jsval-    }-    | DomifiedPwTextNode String jsval--data OldStuff state jsval = OldStuff {-  _oldState :: state,-  _oldDom :: Maybe (DomifiedPwNode jsval)-}------------ reader functions---freeAttrFunction :: DomifiedAttribute jsval -> ReaderT (Browserful jsval) IO ()-freeAttrFunction (DomifiedFunctionAttribute f) = do-  __freeCallback <- asks _freeCallback-  liftIO (void $ __freeCallback f)-freeAttrFunction _ = return ()--freeFunctions :: DomifiedPwNode jsval -> ReaderT (Browserful jsval) IO ()-freeFunctions (DomifiedPwElement _ b c _) = do-  mapM_ freeAttrFunction (fmap snd b)-  mapM_ freeFunctions    c-freeFunctions _ = pure ()--data AttributeHack = MkAttributeHack-  { _hackishStyle    :: HM.HashMap String String-  , _hackishClass    :: S.Set String-  , _hackishSimple   :: HM.HashMap String String-  } deriving (Eq)--getStyleFrom :: [(String, String)] -> HM.HashMap String String-getStyleFrom l = HM.unions-  (fmap stylishAttributes $ filter (\(x, _) -> x == "style") l) where-  stylishAttributes :: (String, String) -> HM.HashMap String String-  stylishAttributes (_, y) = HM.fromList $ fmap-    (\s -> let ss = splitOn ":" s in (ss !! 0, ss !! 1))-    (filter (\x -> elem ':' x) (splitOn ";" y))--getClassFrom :: [(String, String)] -> S.Set String-getClassFrom l = S.unions-  (fmap classyAttributes $ filter (\(x, _) -> x == "class") l) where-  classyAttributes :: (String, String) -> S.Set String-  classyAttributes (_, y) = S.fromList (words y)--getSimpleFrom :: [(String, String)] -> HM.HashMap String String-getSimpleFrom l = HM.unions (fmap simplyAttributes l) where-  simplyAttributes :: (String, String) -> HM.HashMap String String-  simplyAttributes (x, y) =-    if (x /= "class" && x /= "style") then HM.singleton x y else HM.empty--attributeListToSplitAttrs :: [(String, String)] -> AttributeHack-attributeListToSplitAttrs fl =-  MkAttributeHack (getStyleFrom fl) (getClassFrom fl) (getSimpleFrom fl)--isDText :: (String, DomifiedAttribute jsval) -> Maybe (String, String)-isDText (k, DomifiedTextAttribute v) = Just (k, v)-isDText _                         = Nothing--isPwText :: (String, PwAttribute s jsval) -> Maybe (String, String)-isPwText (k, PwTextAttribute v) = Just (k, v)-isPwText _                   = Nothing---daToF :: [(String, DomifiedAttribute jsval)] -> [(String, String)]-daToF l = catMaybes $ fmap isDText l--paToF :: [(String, PwAttribute s jsval)] -> [(String, String)]-paToF l = catMaybes $ fmap isPwText l--nodesEq-  :: String-  -> String-  -> [(String, DomifiedAttribute jsval)]-  -> [(String, PwAttribute s jsval)]-  -> Bool-nodesEq t0 t1 a0 a1 =-  (t0 == t1)-    && (  attributeListToSplitAttrs (daToF a0)-       == attributeListToSplitAttrs (paToF a1)-       )--padr :: Int -> a -> [a] -> [a]-padr i v l = if (length l >= i) then l else padr i v (l ++ [v])--reconcile-  :: Bool-  -> IORef (OldStuff state jsval)-  -> (state -> PwNode state jsval)-  -> jsval-  -> jsval-  -> Maybe (DomifiedPwNode jsval)-  -> Maybe (HydratedPwNode state jsval)-  -> ReaderT-       (Browserful jsval)-       IO-       (Maybe (DomifiedPwNode jsval))-reconcile touchDOM refToOldStuff domCreationF parentNode topLevelNode (Just (DomifiedPwElement currentTag currentAttributes currentChildren currentNode)) (Just maybeNewNode@(HydratedPwElement maybeNewTag maybeNewAttributes maybeNewChildren))-  = if (nodesEq currentTag maybeNewTag currentAttributes maybeNewAttributes)-    then-      (do-        let maxlen = max (length maybeNewChildren) (length currentChildren)-        newChildren <- sequence $ getZipList-          (   (reconcile touchDOM-                         refToOldStuff-                         domCreationF-                         currentNode-                         topLevelNode-              )-          <$> (ZipList (padr maxlen Nothing (fmap Just currentChildren)))-          <*> (ZipList (padr maxlen Nothing (fmap Just maybeNewChildren)))-          )-        currentAttributes <- mapM-          (hydratedAttrToDomifiedAttr refToOldStuff domCreationF parentNode)-          maybeNewAttributes-        if touchDOM-          then-            (do-              mapM_ (removeEventHandler currentNode) currentAttributes-              mapM_ (setEventHandler currentNode)    currentAttributes-            )-          else (pure ())-        return $ Just-          (DomifiedPwElement currentTag-                             currentAttributes-                             (catMaybes newChildren)-                             currentNode-          )-      )-    else-      (do-        res <- domify touchDOM-                      refToOldStuff-                      domCreationF-                      parentNode-                      topLevelNode-                      (Just currentNode)-                      maybeNewNode-        return $ Just res-      )-reconcile touchDOM refToOldStuff domCreationF parentNode topLevelNode (Just currentDomifiedString@(DomifiedPwTextNode currentString currentNode)) (Just maybeNewNode@(HydratedPwTextNode maybeNewString))-  = if (currentString == maybeNewString)-    then pure (Just currentDomifiedString)-    else-      (do-        res <- domify touchDOM-                      refToOldStuff-                      domCreationF-                      parentNode-                      topLevelNode-                      (Just currentNode)-                      maybeNewNode-        return $ Just res-      )-reconcile touchDOM refToOldStuff domCreationF parentNode topLevelNode (Just (DomifiedPwElement _ _ _ currentNode)) (Just maybeNewNode@(HydratedPwTextNode _))-  = do-    res <- domify touchDOM-                  refToOldStuff-                  domCreationF-                  parentNode-                  topLevelNode-                  (Just currentNode)-                  maybeNewNode-    return $ Just res-reconcile touchDOM refToOldStuff domCreationF parentNode topLevelNode (Just (DomifiedPwTextNode _ currentNode)) (Just maybeNewNode@(HydratedPwElement _ _ _))-  = do-    res <- domify touchDOM-                  refToOldStuff-                  domCreationF-                  parentNode-                  topLevelNode-                  (Just currentNode)-                  maybeNewNode-    return $ Just res-reconcile touchDOM refToOldStuff domCreationF parentNode topLevelNode Nothing (Just maybeNewNode)-  = do-    res <- domify touchDOM-                  refToOldStuff-                  domCreationF-                  parentNode-                  topLevelNode-                  Nothing-                  maybeNewNode-    return $ Just res-reconcile touchDOM refToOldStuff domCreationF parentNode _ (Just (DomifiedPwElement _ _ _ currentNode)) Nothing-  = if (touchDOM)-    then-      (do-        _nodeRemoveChild <- asks nodeRemoveChild-        liftIO $ _nodeRemoveChild parentNode currentNode-        return Nothing-      )-    else (pure Nothing)-reconcile touchDOM refToOldStuff domCreationF parentNode _ (Just (DomifiedPwTextNode _ currentNode)) Nothing-  = if (touchDOM)-    then-      (do-        _nodeRemoveChild <- asks nodeRemoveChild-        liftIO $ _nodeRemoveChild parentNode currentNode-        return Nothing-      )-    else (pure Nothing)-reconcile _ _ _ _ _ _ _ = error "Inconsistent state"--reconcileAndAdd = reconcile True--cbMaker-  :: IORef (OldStuff state jsval)-  -> (state -> PwNode state jsval)-  -> jsval-  -> (jsval -> state -> IO state)-  -> Browserful jsval-  -> jsval-  -> IO ()-cbMaker refToOldStuff domCreationF topLevelNode eventToState env event = do-  oldStuff <- readIORef refToOldStuff-  let oldDom   = _oldDom oldStuff-  let oldState = _oldState oldStuff-  newState <- eventToState event oldState-  let newHydratedDom = hydrate newState domCreationF-  newDom <- runReaderT-    (reconcileAndAdd refToOldStuff-                     domCreationF-                     topLevelNode-                     topLevelNode-                     oldDom-                     (Just newHydratedDom)-    )-    env-  maybe (pure ()) (\x -> runReaderT (freeFunctions x) env) oldDom-  writeIORef refToOldStuff (OldStuff newState newDom)--eventable-  :: IORef (OldStuff state jsval)-  -> (state -> PwNode state jsval)-  -> jsval-  -> (jsval -> state -> IO state)-  -> ReaderT (Browserful jsval) IO jsval-eventable refToOldStuff domCreationF topLevelNode eventToState = do-  __makeHaskellCallback <- asks _makeHaskellCallback-  env                   <- ask-  liftIO $ __makeHaskellCallback-    (cbMaker refToOldStuff domCreationF topLevelNode eventToState env)--hydratedAttrToDomifiedAttr-  :: IORef (OldStuff state jsval)-  -> (state -> PwNode state jsval)-  -> jsval-  -> (String, PwAttribute state jsval)-  -> ReaderT (Browserful jsval) IO (String, DomifiedAttribute jsval)-hydratedAttrToDomifiedAttr refToOldStuff domCreationF topLevelNode (k, PwTextAttribute t)-  = return $ (k, DomifiedTextAttribute t)-hydratedAttrToDomifiedAttr refToOldStuff domCreationF topLevelNode (k, PwFunctionAttribute f)-  = do-    func <- eventable refToOldStuff domCreationF topLevelNode f-    return $ (k, DomifiedFunctionAttribute func)--setAtt-  :: jsval-  -> (String, DomifiedAttribute jsval)-  -> ReaderT (Browserful jsval) IO ()-setAtt currentNode (k, DomifiedTextAttribute v) = do-  _elementSetAttribute <- asks elementSetAttribute-  liftIO $ _elementSetAttribute currentNode k v-setAtt currentNode kv = setEventHandler currentNode kv--handleOnlyEventListener-  :: (jsval -> String -> jsval -> IO ())-  -> jsval-  -> (String, DomifiedAttribute jsval)-  -> IO ()-handleOnlyEventListener eventListenerHandlerF currentNode (k, DomifiedFunctionAttribute v)-  = eventListenerHandlerF currentNode k v-handleOnlyEventListener _ _ _ = pure ()--setEventHandler-  :: jsval-  -> (String, DomifiedAttribute jsval)-  -> ReaderT (Browserful jsval) IO ()-setEventHandler currentNode domifiedAttribute = do-  _eventTargetAddEventListener <- asks eventTargetAddEventListener-  liftIO $ handleOnlyEventListener _eventTargetAddEventListener-                                   currentNode-                                   domifiedAttribute--removeEventHandler-  :: jsval-  -> (String, DomifiedAttribute jsval)-  -> ReaderT (Browserful jsval) IO ()-removeEventHandler currentNode domifiedAttribute = do-  _eventTargetRemoveEventListener <- asks eventTargetRemoveEventListener-  liftIO $ handleOnlyEventListener _eventTargetRemoveEventListener-                                   currentNode-                                   domifiedAttribute--domify-  :: Bool-  -> IORef (OldStuff state jsval)-  -> (state -> PwNode state jsval)-  -> jsval-  -> jsval-  -> Maybe jsval-  -> HydratedPwNode state jsval-  -> ReaderT (Browserful jsval) IO (DomifiedPwNode jsval)-domify touchDOM refToOldStuff domCreationF parentNode topLevelNode replacing (HydratedPwElement tag attrs children)-  = do-    _documentCreateElement <- asks documentCreateElement-    _nodeAppendChild       <- asks nodeAppendChild-    _nodeInsertBefore      <- asks nodeInsertBefore-    _nodeRemoveChild       <- asks nodeRemoveChild-    newNode                <- liftIO $ _documentCreateElement tag-    newAttributes          <- mapM-      (hydratedAttrToDomifiedAttr refToOldStuff domCreationF topLevelNode)-      attrs-    if touchDOM then (mapM_ (setAtt newNode) newAttributes) else (pure ())-    newChildren <- mapM-      (domify touchDOM refToOldStuff domCreationF newNode topLevelNode Nothing)-      children-    if touchDOM-      then-        (do-          maybe-            (liftIO $ _nodeAppendChild parentNode newNode)-            (\x -> do-              liftIO $ _nodeInsertBefore parentNode newNode x-              liftIO $ _nodeRemoveChild parentNode x-            )-            replacing-        )-      else (pure ())-    liftIO $ return (DomifiedPwElement tag newAttributes newChildren newNode)-domify touchDOM _ _ parentNode topLevelNode replacing (HydratedPwTextNode text)-  = do-    _documentCreateElement  <- asks documentCreateElement-    _nodeAppendChild        <- asks nodeAppendChild-    _nodeInsertBefore       <- asks nodeInsertBefore-    _nodeRemoveChild        <- asks nodeRemoveChild-    _documentCreateTextNode <- asks documentCreateTextNode-    newTextNode             <- liftIO $ _documentCreateTextNode text-    if touchDOM-      then-        (do-          maybe-            (liftIO $ _nodeAppendChild parentNode newTextNode)-            (\x -> do-              liftIO $ _nodeInsertBefore parentNode newTextNode x-              liftIO $ _nodeRemoveChild parentNode x-            )-            replacing-        )-      else (pure ())-    liftIO $ return (DomifiedPwTextNode text newTextNode)--getChildren :: DomifiedPwNode jsval -> [DomifiedPwNode jsval]-getChildren (DomifiedPwElement _ _ x _) = x-getChildren _                           = []--setEventHandlers_-  :: jsval -> DomifiedPwNode jsval -> ReaderT (Browserful jsval) IO ()-setEventHandlers_ v (DomifiedPwElement _ a _ _) = mapM_ (setEventHandler v) a-setEventHandlers_ _ _                           = liftIO $ pure ()--transformFromCurrentDom-  :: jsval-  -> [DomifiedPwNode jsval]-  -> ReaderT (Browserful jsval) IO [DomifiedPwNode jsval]-transformFromCurrentDom parentNode children = do-  _nodeChildNodes <- asks nodeChildNodes-  _kids           <- liftIO $ _nodeChildNodes parentNode-  let kids = maybe [] id _kids-  newChildren <- sequence $ getZipList-    (   transformFromCurrentDom-    <$> (ZipList kids)-    <*> (ZipList $ fmap getChildren children)-    )-  sequence-    $ getZipList (setEventHandlers_ <$> (ZipList kids) <*> (ZipList children))-  return $ getZipList-    (   (\cur chldrn ptr -> cur { _dom_kids = chldrn, _dom_ptr = ptr })-    <$> (ZipList children)-    <*> (ZipList newChildren)-    <*> (ZipList kids)-    )--addHandlers-  :: jsval-  -> DomifiedPwNode jsval-  -> ReaderT (Browserful jsval) IO (DomifiedPwNode jsval)-addHandlers parentNode curDom = do-  transformed <- transformFromCurrentDom parentNode [curDom]-  return $ (transformed !! 0)--__plzwrk-  :: Bool-  -> (state -> PwNode state jsval)-  -> state-  -> jsval-  -> Browserful jsval-  -> IO (Maybe (DomifiedPwNode jsval))-__plzwrk cleanDOM domF state parentNode env = do-  refToOldStuff <- newIORef (OldStuff state Nothing)-  newDom        <- runReaderT-    (reconcile cleanDOM-               refToOldStuff-               domF-               parentNode-               parentNode-               Nothing-               (Just $ hydrate state domF)-    )-    env-  writeIORef refToOldStuff (OldStuff state newDom)-  if (not cleanDOM)-    then-      (maybe-        (pure Nothing)-        (\y -> do-          withHandlers <- runReaderT (addHandlers parentNode y) env-          writeIORef refToOldStuff (OldStuff state (Just y))-          return $ Just withHandlers-        )-        newDom-      )-    else pure newDom--_plzwrk-  :: Bool-  -> (state -> PwNode state jsval)-  -> state-  -> Browserful jsval-  -> String-  -> IO (Maybe (DomifiedPwNode jsval))-_plzwrk cleanDOM domF state env nodeId = do-  parentNode <- (documentGetElementById env) nodeId-  maybe (error ("Node with id not in DOM: " <> show nodeId))-        (\x -> __plzwrk cleanDOM domF state x env)-        parentNode----- |The main function that makes a web app.--plzwrk-  :: (state -> PwNode state jsval) -- ^ A function that takes a state and produces a DOM-  -> state -- ^ An initial state-  -> Browserful jsval -- ^ A browser implementation, ie Asterius or the mock browser-  -> String -- ^ The id of the element into which the DOM is inserted. Note that plzwrk manages all children under this element. Touching the managed elements can break plzwrk.-  -> IO () -- ^ Returns nothing--plzwrk domF state env nodeId = void $ _plzwrk True domF state env nodeId---- |A variant of plzwrk that acts on a node already rendered to the DOM,---- ie by server-side rendering. It assumes the node has been rendered---- with the same state-to-node function as well as the same state.--plzwrkSSR-  :: (state -> PwNode state jsval) -- ^ A function that takes a state and produces a DOM-  -> state -- ^ An initial state-  -> Browserful jsval -- ^ A browser implementation, ie Asterius or the mock browser-  -> String -- ^ The id of the element into which the DOM is inserted. Note that plzwrk manages all children under this element. Touching the managed elements can break plzwrk.-  -> IO () -- ^ Returns nothing--plzwrkSSR domF state env nodeId = void $ _plzwrk False domF state env nodeId--_plzwrk'-  :: Bool-  -> (state -> PwNode state jsval)-  -> state-  -> Browserful jsval-  -> IO (Maybe (DomifiedPwNode jsval))-_plzwrk' cleanDOM domF state env = do-  parentNode <- (documentBody env)-  __plzwrk cleanDOM domF state parentNode env---- |A variation of plzwrk that inserts the node as a child of the document's body.--plzwrk' :: (state -> PwNode state jsval) -> state -> Browserful jsval -> IO ()-plzwrk' domF state env = void $ _plzwrk' True domF state env---- |A variation of plzwrk that inserts the node as a child of the document's body.--plzwrkSSR'-  :: (state -> PwNode state jsval) -> state -> Browserful jsval -> IO ()-plzwrkSSR' domF state env = void $ _plzwrk' False domF state env---- |A variation of plzwrk that takes no state.--plzwrk'_ :: (() -> PwNode () jsval) -> Browserful jsval -> IO ()-plzwrk'_ domF env = plzwrk' domF () env---- |A variation of plzwrkSSR that takes no state.--plzwrkSSR'_ :: (() -> PwNode () jsval) -> Browserful jsval -> IO ()-plzwrkSSR'_ domF env = plzwrkSSR' domF () env+module Web.Framework.Plzwrk.Domify
+  ( plzwrk
+  , plzwrk'
+  , plzwrk'_
+  , plzwrkSSR
+  , plzwrkSSR'
+  , plzwrkSSR'_
+  )
+where
+
+import           Control.Applicative
+import           Data.List.Split
+import           Control.Monad
+import           Control.Monad.Reader
+import           Control.Monad.Trans
+import           Control.Monad.Trans.Maybe
+import qualified Data.HashMap.Strict           as HM
+import           Data.IORef
+import           Data.Maybe                     ( fromMaybe
+                                                , catMaybes
+                                                , mapMaybe
+                                                )
+import qualified Data.Set                      as S
+import           Web.Framework.Plzwrk.Base
+import           Web.Framework.Plzwrk.JSEnv
+import           Web.Framework.Plzwrk.Util
+
+data DomifiedAttribute jsval = DomifiedTextAttribute String | DomifiedFunctionAttribute jsval
+
+data DomifiedPwNode jsval = DomifiedPwElement
+    { _dom_tag  :: String
+    , _dom_attr :: [(String, DomifiedAttribute jsval)]
+    , _dom_kids :: [DomifiedPwNode jsval]
+    , _dom_ptr  :: jsval
+    }
+    | DomifiedPwTextNode String jsval
+
+data OldStuff state jsval = OldStuff {
+  _oldState :: state,
+  _oldDom :: Maybe (DomifiedPwNode jsval)
+}
+
+---------- reader functions
+
+
+freeAttrFunction :: DomifiedAttribute jsval -> ReaderT (JSEnv jsval) IO ()
+freeAttrFunction (DomifiedFunctionAttribute f) = do
+  __freeCallback <- asks _freeCallback
+  liftIO (void $ __freeCallback f)
+freeAttrFunction _ = return ()
+
+freeFunctions :: DomifiedPwNode jsval -> ReaderT (JSEnv jsval) IO ()
+freeFunctions (DomifiedPwElement _ b c _) = do
+  mapM_ freeAttrFunction (fmap snd b)
+  mapM_ freeFunctions    c
+freeFunctions _ = pure ()
+
+data AttributeHack = MkAttributeHack
+  { _hackishStyle    :: HM.HashMap String String
+  , _hackishClass    :: S.Set String
+  , _hackishSimple   :: HM.HashMap String String
+  } deriving (Eq)
+
+getStyleFrom :: [(String, String)] -> HM.HashMap String String
+getStyleFrom l = HM.unions
+  (fmap stylishAttributes (filter (\(x, _) -> x == "style") l)) where
+  stylishAttributes :: (String, String) -> HM.HashMap String String
+  stylishAttributes (_, y) = HM.fromList $ fmap
+    (\s -> let ss = splitOn ":" s in (head ss, ss !! 1))
+    (filter (elem ':') (splitOn ";" y))
+
+getClassFrom :: [(String, String)] -> S.Set String
+getClassFrom l = S.unions
+  (fmap classyAttributes (filter (\(x, _) -> x == "class") l)) where
+  classyAttributes :: (String, String) -> S.Set String
+  classyAttributes (_, y) = S.fromList (words y)
+
+getSimpleFrom :: [(String, String)] -> HM.HashMap String String
+getSimpleFrom l = HM.unions (fmap simplyAttributes l) where
+  simplyAttributes :: (String, String) -> HM.HashMap String String
+  simplyAttributes (x, y) =
+    if x /= "class" && x /= "style" then HM.singleton x y else HM.empty
+
+attributeListToSplitAttrs :: [(String, String)] -> AttributeHack
+attributeListToSplitAttrs fl =
+  MkAttributeHack (getStyleFrom fl) (getClassFrom fl) (getSimpleFrom fl)
+
+isDText :: (String, DomifiedAttribute jsval) -> Maybe (String, String)
+isDText (k, DomifiedTextAttribute v) = Just (k, v)
+isDText _                            = Nothing
+
+isPwText :: (String, PwAttribute s jsval) -> Maybe (String, String)
+isPwText (k, PwTextAttribute v) = Just (k, v)
+isPwText _                      = Nothing
+
+
+daToF :: [(String, DomifiedAttribute jsval)] -> [(String, String)]
+daToF = mapMaybe isDText
+
+paToF :: [(String, PwAttribute s jsval)] -> [(String, String)]
+paToF = mapMaybe isPwText
+
+nodesEq
+  :: String
+  -> String
+  -> [(String, DomifiedAttribute jsval)]
+  -> [(String, PwAttribute s jsval)]
+  -> Bool
+nodesEq t0 t1 a0 a1 =
+  (t0 == t1)
+    && (  attributeListToSplitAttrs (daToF a0)
+       == attributeListToSplitAttrs (paToF a1)
+       )
+
+padr :: Int -> a -> [a] -> [a]
+padr i v l = if length l >= i then l else padr i v (l ++ [v])
+
+getOpaque :: DomifiedPwNode jsval -> jsval
+getOpaque (DomifiedPwElement _ _ _ x) = x
+getOpaque (DomifiedPwTextNode _ x   ) = x
+
+reconcile
+  :: Bool
+  -> IORef (OldStuff state jsval)
+  -> (state -> PwNode state jsval)
+  -> jsval
+  -> jsval
+  -> Maybe (DomifiedPwNode jsval)
+  -> Maybe (HydratedPwNode state jsval)
+  -> ReaderT
+       (JSEnv jsval)
+       IO
+       (Maybe (DomifiedPwNode jsval))
+reconcile touchDOM refToOldStuff domCreationF parentNode topLevelNode (Just (DomifiedPwElement currentTag currentAttributes currentChildren currentNode)) (Just maybeNewNode@(HydratedPwElement maybeNewTag maybeNewAttributes maybeNewChildren))
+  = if nodesEq currentTag maybeNewTag currentAttributes maybeNewAttributes
+    then
+      (do
+        let maxlen = max (length maybeNewChildren) (length currentChildren)
+        newChildren <- sequence $ getZipList
+          (   reconcile touchDOM
+                        refToOldStuff
+                        domCreationF
+                        currentNode
+                        topLevelNode
+          <$> ZipList (padr maxlen Nothing (fmap Just currentChildren))
+          <*> ZipList (padr maxlen Nothing (fmap Just maybeNewChildren))
+          )
+        newerAttributes <- mapM
+          (hydratedAttrToDomifiedAttr refToOldStuff domCreationF parentNode)
+          maybeNewAttributes
+        if touchDOM
+          then
+            (do
+              mapM_ (removeEventHandler currentNode) currentAttributes
+              mapM_ (setEventHandler currentNode)    newerAttributes
+            )
+          else pure ()
+        return $ Just
+          (DomifiedPwElement currentTag
+                             newerAttributes
+                             (catMaybes newChildren)
+                             currentNode
+          )
+      )
+    else
+      (do
+        res <- domify touchDOM
+                      refToOldStuff
+                      domCreationF
+                      parentNode
+                      topLevelNode
+                      (Just currentNode)
+                      maybeNewNode
+        return $ Just res
+      )
+reconcile touchDOM refToOldStuff domCreationF parentNode topLevelNode (Just currentDomifiedString@(DomifiedPwTextNode currentString currentNode)) (Just maybeNewNode@(HydratedPwTextNode maybeNewString))
+  = if currentString == maybeNewString
+    then pure (Just currentDomifiedString)
+    else
+      (do
+        res <- domify touchDOM
+                      refToOldStuff
+                      domCreationF
+                      parentNode
+                      topLevelNode
+                      (Just currentNode)
+                      maybeNewNode
+        return $ Just res
+      )
+reconcile touchDOM refToOldStuff domCreationF parentNode topLevelNode (Just (DomifiedPwElement _ _ _ currentNode)) (Just maybeNewNode@(HydratedPwTextNode _))
+  = do
+    res <- domify touchDOM
+                  refToOldStuff
+                  domCreationF
+                  parentNode
+                  topLevelNode
+                  (Just currentNode)
+                  maybeNewNode
+    return $ Just res
+reconcile touchDOM refToOldStuff domCreationF parentNode topLevelNode (Just (DomifiedPwTextNode _ currentNode)) (Just maybeNewNode@(HydratedPwElement _ _ _))
+  = do
+    res <- domify touchDOM
+                  refToOldStuff
+                  domCreationF
+                  parentNode
+                  topLevelNode
+                  (Just currentNode)
+                  maybeNewNode
+    return $ Just res
+reconcile touchDOM refToOldStuff domCreationF parentNode topLevelNode Nothing (Just maybeNewNode)
+  = do
+    res <- domify touchDOM
+                  refToOldStuff
+                  domCreationF
+                  parentNode
+                  topLevelNode
+                  Nothing
+                  maybeNewNode
+    return $ Just res
+reconcile touchDOM refToOldStuff domCreationF parentNode _ (Just domifiedPwNode) Nothing
+  = if touchDOM
+    then
+      (do
+        _nodeRemoveChild <- asks nodeRemoveChild
+        liftIO $ _nodeRemoveChild parentNode (getOpaque domifiedPwNode)
+        return Nothing
+      )
+    else pure Nothing
+reconcile _ _ _ _ _ _ _ = error "Inconsistent state"
+
+reconcileAndAdd = reconcile True
+
+cbMaker
+  :: IORef (OldStuff state jsval)
+  -> (state -> PwNode state jsval)
+  -> jsval
+  -> (jsval -> state -> IO state)
+  -> JSEnv jsval
+  -> jsval
+  -> IO ()
+cbMaker refToOldStuff domCreationF topLevelNode eventToState env event = do
+  oldStuff <- readIORef refToOldStuff
+  let oldDom   = _oldDom oldStuff
+  let oldState = _oldState oldStuff
+  newState <- eventToState event oldState
+  let newHydratedDom = hydrate newState domCreationF
+  newDom <- runReaderT
+    (reconcileAndAdd refToOldStuff
+                     domCreationF
+                     topLevelNode
+                     topLevelNode
+                     oldDom
+                     (Just newHydratedDom)
+    )
+    env
+  maybe (pure ()) (\x -> runReaderT (freeFunctions x) env) oldDom
+  writeIORef refToOldStuff (OldStuff newState newDom)
+
+eventable
+  :: IORef (OldStuff state jsval)
+  -> (state -> PwNode state jsval)
+  -> jsval
+  -> (jsval -> state -> IO state)
+  -> ReaderT (JSEnv jsval) IO jsval
+eventable refToOldStuff domCreationF topLevelNode eventToState = do
+  __makeHaskellCallback1 <- asks _makeHaskellCallback1
+  env                    <- ask
+  liftIO $ __makeHaskellCallback1
+    (cbMaker refToOldStuff domCreationF topLevelNode eventToState env)
+
+hydratedAttrToDomifiedAttr
+  :: IORef (OldStuff state jsval)
+  -> (state -> PwNode state jsval)
+  -> jsval
+  -> (String, PwAttribute state jsval)
+  -> ReaderT (JSEnv jsval) IO (String, DomifiedAttribute jsval)
+hydratedAttrToDomifiedAttr refToOldStuff domCreationF topLevelNode (k, PwTextAttribute t)
+  = return (k, DomifiedTextAttribute t)
+hydratedAttrToDomifiedAttr refToOldStuff domCreationF topLevelNode (k, PwFunctionAttribute f)
+  = do
+    func <- eventable refToOldStuff domCreationF topLevelNode f
+    return (k, DomifiedFunctionAttribute func)
+
+setAtt
+  :: jsval
+  -> (String, DomifiedAttribute jsval)
+  -> ReaderT (JSEnv jsval) IO ()
+setAtt currentNode (k, DomifiedTextAttribute v) = do
+  _elementSetAttribute <- asks elementSetAttribute
+  liftIO $ _elementSetAttribute currentNode k v
+setAtt currentNode kv = setEventHandler currentNode kv
+
+handleOnlyEventListener
+  :: (jsval -> String -> jsval -> IO ())
+  -> jsval
+  -> (String, DomifiedAttribute jsval)
+  -> IO ()
+handleOnlyEventListener eventListenerHandlerF currentNode (k, DomifiedFunctionAttribute v)
+  = eventListenerHandlerF currentNode k v
+handleOnlyEventListener _ _ _ = pure ()
+
+setEventHandler
+  :: jsval
+  -> (String, DomifiedAttribute jsval)
+  -> ReaderT (JSEnv jsval) IO ()
+setEventHandler currentNode domifiedAttribute = do
+  _eventTargetAddEventListener <- asks eventTargetAddEventListener
+  liftIO $ handleOnlyEventListener _eventTargetAddEventListener
+                                   currentNode
+                                   domifiedAttribute
+
+removeEventHandler
+  :: jsval
+  -> (String, DomifiedAttribute jsval)
+  -> ReaderT (JSEnv jsval) IO ()
+removeEventHandler currentNode domifiedAttribute = do
+  _eventTargetRemoveEventListener <- asks eventTargetRemoveEventListener
+  liftIO $ handleOnlyEventListener _eventTargetRemoveEventListener
+                                   currentNode
+                                   domifiedAttribute
+
+domify
+  :: Bool
+  -> IORef (OldStuff state jsval)
+  -> (state -> PwNode state jsval)
+  -> jsval
+  -> jsval
+  -> Maybe jsval
+  -> HydratedPwNode state jsval
+  -> ReaderT (JSEnv jsval) IO (DomifiedPwNode jsval)
+domify touchDOM refToOldStuff domCreationF parentNode topLevelNode replacing (HydratedPwElement tag attrs children)
+  = do
+    _documentCreateElement <- asks documentCreateElement
+    _nodeAppendChild       <- asks nodeAppendChild
+    _nodeInsertBefore      <- asks nodeInsertBefore
+    _nodeRemoveChild       <- asks nodeRemoveChild
+    newNode                <- liftIO $ _documentCreateElement tag
+    newAttributes          <- mapM
+      (hydratedAttrToDomifiedAttr refToOldStuff domCreationF topLevelNode)
+      attrs
+    if touchDOM then mapM_ (setAtt newNode) newAttributes else pure ()
+    newChildren <- mapM
+      (domify touchDOM refToOldStuff domCreationF newNode topLevelNode Nothing)
+      children
+    if touchDOM
+      then maybe
+        (liftIO $ _nodeAppendChild parentNode newNode)
+        (\x -> do
+          liftIO $ _nodeInsertBefore parentNode newNode x
+          liftIO $ _nodeRemoveChild parentNode x
+        )
+        replacing
+      else pure ()
+    liftIO $ return (DomifiedPwElement tag newAttributes newChildren newNode)
+domify touchDOM _ _ parentNode topLevelNode replacing (HydratedPwTextNode text)
+  = do
+    _documentCreateElement  <- asks documentCreateElement
+    _nodeAppendChild        <- asks nodeAppendChild
+    _nodeInsertBefore       <- asks nodeInsertBefore
+    _nodeRemoveChild        <- asks nodeRemoveChild
+    _documentCreateTextNode <- asks documentCreateTextNode
+    newTextNode             <- liftIO $ _documentCreateTextNode text
+    if touchDOM
+      then maybe
+        (liftIO $ _nodeAppendChild parentNode newTextNode)
+        (\x -> do
+          liftIO $ _nodeInsertBefore parentNode newTextNode x
+          liftIO $ _nodeRemoveChild parentNode x
+        )
+        replacing
+      else pure ()
+    liftIO $ return (DomifiedPwTextNode text newTextNode)
+
+getChildren :: DomifiedPwNode jsval -> [DomifiedPwNode jsval]
+getChildren (DomifiedPwElement _ _ x _) = x
+getChildren _                           = []
+
+setEventHandlers_
+  :: jsval -> DomifiedPwNode jsval -> ReaderT (JSEnv jsval) IO ()
+setEventHandlers_ v (DomifiedPwElement _ a _ _) = mapM_ (setEventHandler v) a
+setEventHandlers_ _ _                           = liftIO $ pure ()
+
+transformFromCurrentDom
+  :: jsval
+  -> [DomifiedPwNode jsval]
+  -> ReaderT (JSEnv jsval) IO [DomifiedPwNode jsval]
+transformFromCurrentDom parentNode children = do
+  _nodeChildNodes <- asks nodeChildNodes
+  _kids           <- liftIO $ _nodeChildNodes parentNode
+  let kids = fromMaybe [] _kids
+  newChildren <- sequence $ getZipList
+    (   transformFromCurrentDom
+    <$> ZipList kids
+    <*> ZipList (fmap getChildren children)
+    )
+  sequence_
+    $ getZipList (setEventHandlers_ <$> ZipList kids <*> ZipList children)
+  return $ getZipList
+    (   (\cur chldrn ptr -> cur { _dom_kids = chldrn, _dom_ptr = ptr })
+    <$> ZipList children
+    <*> ZipList newChildren
+    <*> ZipList kids
+    )
+
+addHandlers
+  :: jsval
+  -> DomifiedPwNode jsval
+  -> ReaderT (JSEnv jsval) IO (DomifiedPwNode jsval)
+addHandlers parentNode curDom = do
+  transformed <- transformFromCurrentDom parentNode [curDom]
+  return (head transformed)
+
+__plzwrk
+  :: Bool
+  -> (state -> PwNode state jsval)
+  -> state
+  -> jsval
+  -> JSEnv jsval
+  -> IO (Maybe (DomifiedPwNode jsval))
+__plzwrk cleanDOM domF state parentNode env = do
+  refToOldStuff <- newIORef (OldStuff state Nothing)
+  newDom        <- runReaderT
+    (reconcile cleanDOM
+               refToOldStuff
+               domF
+               parentNode
+               parentNode
+               Nothing
+               (Just $ hydrate state domF)
+    )
+    env
+  writeIORef refToOldStuff (OldStuff state newDom)
+  if not cleanDOM
+    then maybe
+        (pure Nothing)
+        (\y -> do
+          withHandlers <- runReaderT (addHandlers parentNode y) env
+          writeIORef refToOldStuff (OldStuff state (Just y))
+          return $ Just withHandlers
+        )
+        newDom
+    else pure newDom
+
+_plzwrk
+  :: Bool
+  -> (state -> PwNode state jsval)
+  -> state
+  -> JSEnv jsval
+  -> String
+  -> IO (Maybe (DomifiedPwNode jsval))
+_plzwrk cleanDOM domF state env nodeId = do
+  parentNode <- documentGetElementById env nodeId
+  maybe (error ("Node with id not in DOM: " <> show nodeId))
+        (\x -> __plzwrk cleanDOM domF state x env)
+        parentNode
+
+
+-- |The main function that makes a web app.
+
+plzwrk
+  :: (state -> PwNode state jsval) -- ^ A function that takes a state and produces a DOM
+  -> state -- ^ An initial state
+  -> JSEnv jsval -- ^ A browser implementation, ie Asterius or the mock browser
+  -> String -- ^ The id of the element into which the DOM is inserted. Note that plzwrk manages all children under this element. Touching the managed elements can break plzwrk.
+  -> IO () -- ^ Returns nothing
+
+plzwrk domF state env nodeId = void $ _plzwrk True domF state env nodeId
+
+-- |A variant of plzwrk that acts on a node already rendered to the DOM,
+
+-- ie by server-side rendering. It assumes the node has been rendered
+
+-- with the same state-to-node function as well as the same state.
+
+plzwrkSSR
+  :: (state -> PwNode state jsval) -- ^ A function that takes a state and produces a DOM
+  -> state -- ^ An initial state
+  -> JSEnv jsval -- ^ A browser implementation, ie Asterius or the mock browser
+  -> String -- ^ The id of the element into which the DOM is inserted. Note that plzwrk manages all children under this element. Touching the managed elements can break plzwrk.
+  -> IO () -- ^ Returns nothing
+
+plzwrkSSR domF state env nodeId = void $ _plzwrk False domF state env nodeId
+
+_plzwrk'
+  :: Bool
+  -> (state -> PwNode state jsval)
+  -> state
+  -> JSEnv jsval
+  -> IO (Maybe (DomifiedPwNode jsval))
+_plzwrk' cleanDOM domF state env = do
+  parentNode <- documentBody env
+  __plzwrk cleanDOM domF state parentNode env
+
+-- |A variation of plzwrk that inserts the node as a child of the document's body.
+
+plzwrk' :: (state -> PwNode state jsval) -> state -> JSEnv jsval -> IO ()
+plzwrk' domF state env = void $ _plzwrk' True domF state env
+
+-- |A variation of plzwrk that inserts the node as a child of the document's body.
+
+plzwrkSSR'
+  :: (state -> PwNode state jsval) -> state -> JSEnv jsval -> IO ()
+plzwrkSSR' domF state env = void $ _plzwrk' False domF state env
+
+-- |A variation of plzwrk that takes no state.
+
+plzwrk'_ :: (() -> PwNode () jsval) -> JSEnv jsval -> IO ()
+plzwrk'_ domF = plzwrk' domF ()
+
+-- |A variation of plzwrkSSR that takes no state.
+
+plzwrkSSR'_ :: (() -> PwNode () jsval) -> JSEnv jsval -> IO ()
+plzwrkSSR'_ domF = plzwrkSSR' domF ()
+ src/Web/Framework/Plzwrk/JSEnv.hs view
@@ -0,0 +1,137 @@+module Web.Framework.Plzwrk.JSEnv
+  ( JSEnv(..)
+  , RequestInit(..)
+  , FetchBody(..)
+  )
+where
+
+import           Data.ByteString.Internal  ( ByteString )
+import qualified Data.HashMap.Strict      as HM
+
+-- | A data class holding functions that operate on opaque
+-- JavaScript types, parameterized by @jsval@. When possible,
+-- the real names of browser functions like 'addEventListener'
+-- and 'appendChild' are used.
+--
+-- JSEnv is currently implemented as data instead of as
+-- a typeclass because it is unclear what type of additional
+-- monadic transformer around IO would be most appropriate to
+-- retain the state of @jsval@ objects, whereas when part of
+-- a dataclass, the state retention is abstracted away.
+
+data JSEnv jsval = JSEnv
+  {
+    -- | Casts a value to an array of jsvals
+    castToArray                  :: jsval -> IO (Maybe [jsval])
+
+    -- | Casts a value to a bool
+  , castToBool                    :: jsval -> IO (Maybe Bool)
+
+    -- | Casts a value to a bool
+  , castToByteString              :: jsval -> IO (Maybe ByteString)
+
+    -- | Casts a value to a double
+  , castToDouble                  :: jsval -> IO (Maybe Double)
+
+    -- | Casts a value to an int
+  , castToInt                     :: jsval -> IO (Maybe Int)
+
+    -- | Casts a value to a string
+  , castToString                  :: jsval -> IO (Maybe String)
+
+    -- | Logs an opaque JavaScript value. See [Console.log](https://developer.mozilla.org/en-US/docs/Web/API/Console/log)
+  , consoleLog                     :: jsval -> IO ()
+
+    -- | A default request init
+  , defaultRequestInit             :: RequestInit jsval
+
+    -- | The body of the document. See [Document.body](https://developer.mozilla.org/en-US/docs/Web/API/Document/body)
+  , documentBody                   :: IO jsval
+
+    -- | Creates an element with a given tag. See [Document.createElement](https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement)
+  , documentCreateElement          :: String -> IO jsval
+
+    -- | Creates a text node with the given text. See [Document.createTextNode](https://developer.mozilla.org/en-US/docs/Web/API/Document/createTextNode)
+  , documentCreateTextNode         :: String -> IO jsval
+
+    -- | Gets an element by id from a document. See [Document.getElementById](https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById)
+  , documentGetElementById         :: String -> IO (Maybe jsval)
+
+    -- | Gets the head of a document. See [Document.head](https://developer.mozilla.org/en-US/docs/Web/API/Document/head)
+  , documentHead                   :: IO jsval
+
+    -- | Calls the browser's fetch command
+  , fetch                          :: String -> RequestInit jsval -> IO jsval
+
+    -- | Gets a JavaScript property, returning @Nothing@ if the object being called is null or undefined.
+  , getPropertyAsOpaque            :: jsval -> String -> IO (Maybe jsval)
+
+    -- | Invokes on target a function with 0 arguments.
+  , invokeOn0                      :: jsval -> String -> IO jsval
+
+    -- | Invokes on target a function with 1 argument.
+  , invokeOn1                      :: jsval -> String -> jsval -> IO jsval
+
+    -- | Invokes on target a function with 2 arguments.
+  , invokeOn2                      :: jsval -> String -> jsval -> jsval -> IO jsval
+
+    -- | jsval from an array of jsvals
+  , jsValFromArray                 :: [jsval] -> IO jsval
+
+    -- | jsval from a bool
+  , jsValFromBool                  :: Bool -> IO jsval
+
+    -- | jsval from a byte string
+  , jsValFromByteString            :: ByteString -> IO jsval
+
+    -- | jsval from a double
+  , jsValFromDouble                :: Double -> IO jsval
+
+    -- | jsval from an int
+  , jsValFromInt                   :: Int -> IO jsval
+
+    -- | jsval from a string
+  , jsValFromString                :: String -> IO jsval
+
+    -- | Creates an object
+  , makeObject                     :: IO jsval
+
+    -- | Generate a random double between 0 and 1. See [Math.random](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random)
+  , mathRandom                     :: IO Double
+
+    -- | Sets on an object a value
+  , setValue                       :: jsval -> String -> jsval -> IO ()
+
+    -- | Frees a callback. Should only be called in advanced cases. In most usage, callbacks are freed automatically by plzwrk.
+  , _freeCallback                  :: jsval -> IO ()
+
+    -- | Makes a haskell callback with one argument. Should only be called in advanced cases. In most usage, callbacks are created automatically by plzwrk.
+  , _makeHaskellCallback1          :: (jsval -> IO ()) -> IO jsval
+
+    -- | Makes a haskell callback with two arguments. Should only be called in advanced cases. In most usage, callbacks are created automatically by plzwrk.
+  , _makeHaskellCallback2          :: (jsval -> jsval -> IO ()) -> IO jsval
+
+    -- | Makes a haskell callback with three arguments. Should only be called in advanced cases. In most usage, callbacks are created automatically by plzwrk.
+  , _makeHaskellCallback3          :: (jsval -> jsval -> jsval -> IO ()) -> IO jsval
+  }
+
+-- |The body of a fetch request or response
+data FetchBody jsval =
+    FormDataBody (HM.HashMap String jsval) -- ^ From form data, ie @multipart/form-data@ or @application/x-www-form-urlencoded@
+  | StringBody   String -- ^ A string, ie @text/plain@ or @application/json@
+  | BlobBody     jsval -- ^ A single file
+  | URLSearchParamsBody (HM.HashMap String String) -- ^ Useful for @application/x-www-form-urlencoded@
+  | Uint8Array   ByteString
+
+-- | Initialization parameters for a request made with fetch
+data RequestInit jsval = RequestInit {
+    _ri_method      :: Maybe String -- ^ The request method, e.g., GET, POST. The default is GET.
+  , _ri_headers     :: Maybe (HM.HashMap String String) -- ^ Any headers you want to add to your request, contained within a Headers object or an object literal with ByteString values.
+  , _ri_body        :: Maybe (FetchBody jsval) -- ^ Any body that you want to add to your request: this can be a Blob, BufferSource, FormData, URLSearchParams, USVString, or ReadableStream object. Note that a request using the GET or HEAD method cannot have a body.
+  , _ri_mode        :: Maybe String -- ^ The mode you want to use for the request, e.g., cors, no-cors, same-origin, or navigate. The default is cors.
+  , _ri_credentials :: Maybe String -- ^ The request credentials you want to use for the request: omit, same-origin, or include. The default is same-origin.
+  , _ri_cache       :: Maybe String -- ^ The cache mode you want to use for the request.
+  , _ri_redirect    :: Maybe String -- ^ The redirect mode to use: follow, error, or manual. The default is follow.
+  , _ri_referrer    :: Maybe String -- ^ A USVString specifying no-referrer, client, or a URL. The default is about:client.
+  , _ri_integrity   :: Maybe String -- ^ Contains the subresource integrity value of the request (e.g., sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=).
+}
src/Web/Framework/Plzwrk/MockJSVal.hs view
@@ -1,15 +1,27 @@ {-|
+
 Module      : Web.Framework.Plzwrk.MockJSVal
+
 Description : Mock browser for testing
+
 Copyright   : (c) Mike Solomon 2020
+
 License     : GPL-3
+
 Maintainer  : mike@meeshkan.com
+
 Stability   : experimental
+
 Portability : POSIX, Windows
 
+
+
 This module exports a mock browser called
+
 @defaultInternalBrowser@ used in plzwrk's tests
+
 and that can be used in your unit tests as well.
+
 -}
 module Web.Framework.Plzwrk.MockJSVal
   ( MockJSVal(..)
@@ -28,7 +40,7 @@ import           Data.List                      ( elemIndex )
 import           Prelude                 hiding ( lookup )
 import           Web.Framework.Plzwrk.Base
-import           Web.Framework.Plzwrk.Browserful
+import           Web.Framework.Plzwrk.JSEnv
 
 data LogEvent = ListenerReceived String Int
     | AddedAsListenerTo Int
@@ -58,7 +70,9 @@ 
 data MockJSVal = MockJSElement Int String MockAttributes [MockJSVal] [LogEvent]
     | MockJSTextNode Int String [LogEvent]
-    | MockJSFunction Int (MockJSVal -> IO ()) [LogEvent]
+    | MockJSFunction1 Int (MockJSVal -> IO ()) [LogEvent]
+    | MockJSFunction2 Int (MockJSVal -> MockJSVal -> IO ()) [LogEvent]
+    | MockJSFunction3 Int (MockJSVal -> MockJSVal -> MockJSVal -> IO ()) [LogEvent]
     | MockJSObject Int (HashMap String Int) [LogEvent]
     | MockJSString Int String [LogEvent]
     | MockJSDouble Int Double [LogEvent]
@@ -81,7 +95,9 @@       <> " "
       <> show e
   show (MockJSTextNode   a b c) = show a <> " " <> show b <> " " <> show c
-  show (MockJSFunction   a _ c) = show a <> " " <> show c
+  show (MockJSFunction1  a _ c) = show a <> " " <> show c
+  show (MockJSFunction2  a _ c) = show a <> " " <> show c
+  show (MockJSFunction3  a _ c) = show a <> " " <> show c
   show (MockJSObject     a b c) = show a <> " " <> show b <> " " <> show c
   show (MockJSString     a b c) = show a <> " " <> show b <> " " <> show c
   show (MockJSDouble     a b c) = show a <> " " <> show b <> " " <> show c
@@ -94,7 +110,9 @@ _withNewLog :: MockJSVal -> [LogEvent] -> MockJSVal
 _withNewLog (MockJSElement a b c d _) log = MockJSElement a b c d log
 _withNewLog (MockJSTextNode   a b _ ) log = MockJSTextNode a b log
-_withNewLog (MockJSFunction   a b _ ) log = MockJSFunction a b log
+_withNewLog (MockJSFunction1  a b _ ) log = MockJSFunction1 a b log
+_withNewLog (MockJSFunction2  a b _ ) log = MockJSFunction2 a b log
+_withNewLog (MockJSFunction3  a b _ ) log = MockJSFunction3 a b log
 _withNewLog (MockJSObject     a b _ ) log = MockJSObject a b log
 _withNewLog (MockJSString     a b _ ) log = MockJSString a b log
 _withNewLog (MockJSDouble     a b _ ) log = MockJSDouble a b log
@@ -116,7 +134,9 @@ _ptr :: MockJSVal -> Int
 _ptr (MockJSElement a _ _ _ _) = a
 _ptr (MockJSTextNode   a _ _ ) = a
-_ptr (MockJSFunction   a _ _ ) = a
+_ptr (MockJSFunction1  a _ _ ) = a
+_ptr (MockJSFunction2  a _ _ ) = a
+_ptr (MockJSFunction3  a _ _ ) = a
 _ptr (MockJSObject     a _ _ ) = a
 _ptr (MockJSString     a _ _ ) = a
 _ptr (MockJSDouble     a _ _ ) = a
@@ -130,12 +150,12 @@   -> String
   -> MockJSVal
   -> IO (MockAttributes, [LogEvent], [LogEvent])
-_eventTargetAddEventListener (MockJSElement n _ (MockAttributes atts lstns) _ logn) evt fn@(MockJSFunction m _ logm)
+_eventTargetAddEventListener (MockJSElement n _ (MockAttributes atts lstns) _ logn) evt fn@(MockJSFunction1 m _ logm)
   = pure
-    $ ( MockAttributes atts $ insert evt fn lstns
-      , logn <> [ListenerReceived evt m]
-      , logm <> [AddedAsListenerTo n]
-      )
+    ( MockAttributes atts $ insert evt fn lstns
+    , logn <> [ListenerReceived evt m]
+    , logm <> [AddedAsListenerTo n]
+    )
 _eventTargetAddEventListener _ _ _ =
   error "Can only add event listener to element"
 
@@ -143,19 +163,17 @@   :: MockJSVal -> String -> String -> IO (MockAttributes, [LogEvent])
 _elementSetAttribute (MockJSElement n _ (MockAttributes atts lstns) _ logn) nm attr
   = pure
-    $ ( MockAttributes (insert nm attr atts) lstns
-      , logn <> [AttributeReceived nm attr]
-      )
+    ( MockAttributes (insert nm attr atts) lstns
+    , logn <> [AttributeReceived nm attr]
+    )
 _elementSetAttribute _ _ _ = error "Can only add event listener to element"
 
 _nodeAppendChild
   :: MockJSVal -> MockJSVal -> IO ([MockJSVal], [LogEvent], [LogEvent])
 _nodeAppendChild (MockJSElement n _ _ kids logn) kid@(MockJSElement m _ _ _ logm)
-  = pure
-    $ (kids <> [kid], logn <> [ChildReceived m], logm <> [AddedAsChildTo n])
+  = pure (kids <> [kid], logn <> [ChildReceived m], logm <> [AddedAsChildTo n])
 _nodeAppendChild (MockJSElement n _ _ kids logn) kid@(MockJSTextNode m _ logm)
-  = pure
-    $ (kids <> [kid], logn <> [ChildReceived m], logm <> [AddedAsChildTo n])
+  = pure (kids <> [kid], logn <> [ChildReceived m], logm <> [AddedAsChildTo n])
 _nodeAppendChild _ _ = error "Can only append element to element"
 
 __nodeRemoveChild
@@ -168,12 +186,11 @@   -> IO ([MockJSVal], [LogEvent], [LogEvent])
 __nodeRemoveChild n kids logn kid m logm = maybe
   (error ("Existing item " <> show m <> " not child of " <> show n))
-  (\x ->
-    pure
-      $ ( take x kids <> drop (x + 1) kids
-        , logn <> [RemovedNode m]
-        , logm <> [RemovedAsNodeFrom n]
-        )
+  (\x -> pure
+    ( take x kids <> drop (x + 1) kids
+    , logn <> [RemovedNode m]
+    , logm <> [RemovedAsNodeFrom n]
+    )
   )
   (elemIndex (_ptr kid) (fmap _ptr kids))
 
@@ -190,15 +207,14 @@   -> String
   -> MockJSVal
   -> IO (MockAttributes, [LogEvent], [LogEvent])
-_eventTargetRemoveEventListener (MockJSElement n _ (MockAttributes atts lstns) _ logn) evt fn@(MockJSFunction m _ logm)
+_eventTargetRemoveEventListener (MockJSElement n _ (MockAttributes atts lstns) _ logn) evt fn@(MockJSFunction1 m _ logm)
   = maybe
     (error ("Listener " <> show m <> " not child of " <> show n))
-    (\x ->
-      pure
-        $ ( MockAttributes atts $ delete evt lstns
-          , logn <> [RemovedListener evt m]
-          , logm <> [RemovedAsListenerFrom n]
-          )
+    (\x -> pure
+      ( MockAttributes atts $ delete evt lstns
+      , logn <> [RemovedListener evt m]
+      , logm <> [RemovedAsListenerFrom n]
+      )
     )
     (lookup evt lstns)
 _eventTargetRemoveEventListener _ _ _ =
@@ -222,13 +238,12 @@        )
 _nodeInsertBeforeInternal n kids logn newI m logm existingI l logl = maybe
   (error ("Existing item " <> show l <> " not child of " <> show n))
-  (\x ->
-    pure
-      $ ( take x kids <> [newI] <> drop x kids
-        , logn <> [InsertedChildBefore m l]
-        , logm <> [InsertedAsChildBefore n l]
-        , logl <> [ElementAddedBefore m]
-        )
+  (\x -> pure
+    ( take x kids <> [newI] <> drop x kids
+    , logn <> [InsertedChildBefore m l]
+    , logm <> [InsertedAsChildBefore n l]
+    , logl <> [ElementAddedBefore m]
+    )
   )
   (elemIndex (_ptr existingI) (fmap _ptr kids))
 
@@ -262,20 +277,29 @@ _nodeChildNodes _ = error "Can only get children of element"
 
 __freeCallback :: MockJSVal -> IO [LogEvent]
-__freeCallback (MockJSFunction n _ log) = pure (log <> [FreeCallback n])
+__freeCallback (MockJSFunction1 n _ log) = pure (log <> [FreeCallback n])
+__freeCallback (MockJSFunction2 n _ log) = pure (log <> [FreeCallback n])
+__freeCallback (MockJSFunction3 n _ log) = pure (log <> [FreeCallback n])
 __freeCallback _                        = error "Can only free function"
 
-dummyClick :: MockJSVal -> IO ()
--- todo give real number
+isFree :: LogEvent -> Bool
+isFree (FreeCallback _) = True
+isFree _ = False
 
+hasFree :: [LogEvent] -> Bool
+hasFree l = or (fmap isFree l)
 
-dummyClick (MockJSFunction _ f _) = f $ MockMouseEvent (-1)
+-- todo give real number
+dummyClick :: MockJSVal -> IO ()
+dummyClick (MockJSFunction1 _ f logs) = do
+  if hasFree logs then error "Trying to call freed callback" else pure ()
+  f $ MockMouseEvent (-1)
 
 
 _htmlElemenetClick :: MockJSVal -> IO ()
 _htmlElemenetClick (MockJSElement _ _ (MockAttributes _ evts) _ _) = do
   let oc = lookup "click" evts
-  maybe (pure ()) (\x -> dummyClick x) oc
+  maybe (pure ()) dummyClick oc
 
 _htmlElemenetClick _ = error "Can only free function"
 
@@ -284,6 +308,7 @@ 
 
 
+
 data MockBrowserInternal = MockBrowserInternal
   { unBrowser :: HashMap Int MockJSVal
   , unCtr     :: Int
@@ -294,8 +319,8 @@ look env elt = do
   r <- readIORef env
   let bz = unBrowser r
-  maybe (error $ "Cannot find object pointer in env: " <> (show elt))
-        (\x -> return x)
+  maybe (error $ "Cannot find object pointer in env: " <> show elt)
+        return
         (lookup elt bz)
 
 incr :: IORef MockBrowserInternal -> IO Int
@@ -338,6 +363,7 @@   return i
 
 ----------------------
+
 _jsValFrom
   :: (Int -> s -> [LogEvent] -> MockJSVal)
   -> IORef MockBrowserInternal
@@ -358,6 +384,7 @@ 
 ----------------------
 
+
 _'mathRandom :: IORef MockBrowserInternal -> IO Double
 _'mathRandom _ = pure 0.5
 
@@ -380,15 +407,15 @@   | s == "tagName" = do
     tn <- _'elementTagName env i
     _v <- _'jsValFromString env tn
-    (return . Just) $ _v
+    (return . Just) _v
   | s == "textContent" = do
     tc <- _'nodeTextContent env i
     _v <- _'jsValFromString env tc
-    (return . Just) $ _v
+    (return . Just) _v
   | s == "childNodes" = do
     cn <- _'nodeChildNodes env i
-    _v <-_'jsValFromArray env cn
-    (return . Just) $ _v
+    _v <- _'jsValFromArray env cn
+    (return . Just) _v
   | otherwise =  error
   $  "This property is not implemented yet in MockJSVal: "
   <> s
@@ -470,10 +497,9 @@ 
 
 _'fetch :: IORef MockBrowserInternal -> String -> RequestInit Int -> IO Int
-_'fetch env _ _ = do
-  _o <- _'makeObject env
-  return _o -- return an empty object for now
+_'fetch env _ _ = _'makeObject env
 
+
 _'elementTagName :: IORef MockBrowserInternal -> Int -> IO String
 _'elementTagName env elt = do
   _elt <- look env elt
@@ -489,8 +515,8 @@   _elt <- look env elt
   _nodeTextContent _elt
 
-_'_freeCallback :: IORef MockBrowserInternal -> Int -> IO ()
-_'_freeCallback env fn = do
+_'freeCallback :: IORef MockBrowserInternal -> Int -> IO ()
+_'freeCallback env fn = do
   _fn    <- look env fn
   newLog <- __freeCallback _fn
   wrt env fn $ _withNewLog _fn newLog
@@ -502,25 +528,25 @@ 
 idEq :: String -> MockJSVal -> Bool
 idEq txt (MockJSElement _ _ (MockAttributes atts _) _ _) =
-  Just txt == (lookup "id" atts)
+  Just txt == lookup "id" atts
 idEq _ _ = False
 
 _'documentBody :: IORef MockBrowserInternal -> IO Int
 _'documentBody ref = do
   mb <- readIORef ref
   let browser = unBrowser mb
-  pt <- maybe (error "No body.") (\x -> pure $ _ptr x) $ lookup 0 browser
-  return pt
+  maybe (error "No body.") (pure . _ptr) (lookup 0 browser)
 
 _'documentHead :: IORef MockBrowserInternal -> IO Int
 _'documentHead ref = pure (-1) -- need to implement in mock?
 
 
+
 _documentGetElementByIdInternal :: MockJSVal -> String -> [Int]
 _documentGetElementByIdInternal jsv@(MockJSElement _ _ _ ch _) txt =
-  if (idEq txt jsv)
+  if idEq txt jsv
     then [_ptr jsv]
-    else (foldr (++) [] $ fmap (\x -> _documentGetElementByIdInternal x txt) ch)
+    else concatMap (`_documentGetElementByIdInternal` txt) ch
 _documentGetElementByIdInternal _ _ = []
 
 _'documentGetElementById
@@ -529,7 +555,7 @@   body  <- _'documentBody env
   _body <- look env body
   let elts = _documentGetElementByIdInternal _body txt
-  return $ if (null elts) then (Nothing) else (Just $ head elts)
+  return $ if null elts then Nothing else Just $ head elts
 
 _'nodeInsertBefore :: IORef MockBrowserInternal -> Int -> Int -> Int -> IO ()
 _'nodeInsertBefore env parent newItem existingItem = do
@@ -542,13 +568,27 @@   wrt env newItem $ _withNewLog _newItem newLogNewItem
   wrt env existingItem $ _withNewLog _existingItem newLogExistingItem
 
-_'_makeHaskellCallback :: IORef MockBrowserInternal -> (Int -> IO ()) -> IO Int
-_'_makeHaskellCallback env cb = do
+_'makeHaskellCallback1 :: IORef MockBrowserInternal -> (Int -> IO ()) -> IO Int
+_'makeHaskellCallback1 env cb = do
   i <- incr env
-  let elt = MockJSFunction i (\x -> cb $ _ptr x) [MadeCallback i]
+  let elt = MockJSFunction1 i (cb . _ptr) [MadeCallback i]
   wrt env i elt
   return i
 
+_'makeHaskellCallback2 :: IORef MockBrowserInternal -> (Int -> Int -> IO ()) -> IO Int
+_'makeHaskellCallback2 env cb = do
+  i <- incr env
+  let elt = MockJSFunction2 i (\x y -> cb (_ptr x) (_ptr y)) [MadeCallback i]
+  wrt env i elt
+  return i
+
+_'makeHaskellCallback3 :: IORef MockBrowserInternal -> (Int -> Int -> Int -> IO ()) -> IO Int
+_'makeHaskellCallback3 env cb = do
+  i <- incr env
+  let elt = MockJSFunction3 i (\x y z -> cb (_ptr x) (_ptr y) (_ptr z)) [MadeCallback i]
+  wrt env i elt
+  return i
+
 _'makeObject :: IORef MockBrowserInternal -> IO Int
 _'makeObject env = do
   i <- incr env
@@ -644,8 +684,8 @@                                    , _ri_integrity   = Nothing
                                    }
 
-makeMockBrowserWithContext :: IORef MockBrowserInternal -> IO (Browserful Int)
-makeMockBrowserWithContext r = return Browserful
+makeMockBrowserWithContext :: IORef MockBrowserInternal -> IO (JSEnv Int)
+makeMockBrowserWithContext r = return JSEnv
   { castToArray            = _'castToArray r
   , castToBool             = _'castToBool r
   , castToByteString       = _'castToByteString r
@@ -660,7 +700,7 @@   , documentGetElementById = _'documentGetElementById r
   , documentHead           = _'documentHead r
   , fetch                  = _'fetch r
-  , _freeCallback          = _'_freeCallback r
+  , _freeCallback          = _'freeCallback r
   , getPropertyAsOpaque    = _'getPropertyAsOpaque r
   , jsValFromArray         = _'jsValFromArray r
   , jsValFromBool          = _'jsValFromBool r
@@ -673,7 +713,9 @@   , setValue               = _'setValue r
   , invokeOn1              = _'invokeOn1 r
   , invokeOn2              = _'invokeOn2 r
-  , _makeHaskellCallback   = _'_makeHaskellCallback r
+  , _makeHaskellCallback1  = _'makeHaskellCallback1 r
+  , _makeHaskellCallback2  = _'makeHaskellCallback2 r
+  , _makeHaskellCallback3  = _'makeHaskellCallback3 r
   , mathRandom             = _'mathRandom r
   }
 
@@ -686,7 +728,7 @@                            [CreatedElement 0]
   newIORef MockBrowserInternal { unBrowser = singleton 0 body, unCtr = 1 }
 
-makeMockBrowser :: IO (Browserful Int)
+makeMockBrowser :: IO (JSEnv Int)
 makeMockBrowser = do
   rf <- defaultInternalBrowser
   makeMockBrowserWithContext rf
src/Web/Framework/Plzwrk/TH/HSX.hs view
@@ -50,7 +50,7 @@   attr <- many attribute
   ws
   close <- try (string "/>" <|> string ">")
-  if (length close) == 2
+  if length close == 2
     then return (HSXSelfClosingTag name attr)
     else do
       elementBody <- many elementHSXBody
@@ -86,12 +86,12 @@   return $ HSXHaskellTxtAttribute value
 
 makeBracketed cmd contain = do
-  let start = ("#" <> cmd <> "{")
+  let start = "#" <> cmd <> "{"
   let end   = "}#"
   string start
   value <- manyTill anyChar (string end)
   ws
-  return $ if (contain) then start <> value <> end else value
+  return $ if contain then start <> value <> end else value
 
 haskellCodeAttr = do
   value <- makeBracketed "c" False
@@ -117,7 +117,7 @@   ws
   char '='
   ws
-  value <- stringAttribute <|> (try haskellCodeAttr) <|> haskellTxtAttr
+  value <- stringAttribute <|> try haskellCodeAttr <|> haskellTxtAttr
   ws
   return (name, value)
 
src/Web/Framework/Plzwrk/TH/QuoteHSX.hs view
@@ -81,7 +81,13 @@     (TH.conE (TH.mkName "PwElement"))     [ TH.litE (TH.StringL tag)     , TH.listE (fmap hsxAttributeToExpQ attrs)-    , foldl TH.appE (TH.varE (TH.mkName "foldr")) [(TH.varE (TH.mkName "plusplus")), (TH.conE (TH.mkName "[]")), TH.listE (fmap (\x -> hsxToExpQ True True x) elts)]+    , foldl+      TH.appE+      (TH.varE (TH.mkName "foldr"))+      [ TH.varE (TH.mkName "plusplus")+      , TH.conE (TH.mkName "[]")+      , TH.listE (fmap (hsxToExpQ True True) elts)+      ]     ]   ) hsxToExpQ lam returnAsList (HSXSelfClosingTag tag attrs) = asList@@ -89,9 +95,9 @@   (wrapInLambda lam $ foldl     TH.appE     (TH.conE (TH.mkName "PwElement"))-    [ (TH.litE (TH.StringL tag))+    [ TH.litE (TH.StringL tag)     , TH.listE (fmap hsxAttributeToExpQ attrs)-    , (TH.conE (TH.mkName "[]"))+    , TH.conE (TH.mkName "[]")     ]   ) hsxToExpQ lam returnAsList (HSXBody b) = asList
src/Web/Framework/Plzwrk/Tag.hs view
@@ -206,12 +206,12 @@ , _data'_
 , _data__
 , _data'__
-, _datalist
-, _datalist'
-, _datalist_
-, _datalist'_
-, _datalist__
-, _datalist'__
+, datalist
+, datalist'
+, datalist_
+, datalist'_
+, datalist__
+, datalist'__
 , dd
 , dd'
 , dd_
@@ -772,8 +772,8 @@ import Web.Framework.Plzwrk.Base
 
 type AFSig s opq
-  = [(String, (s -> PwAttribute s opq))] -> [s -> PwNode s opq] -> (s -> PwNode s opq)
-type Sig s opq = [(String, (s -> PwAttribute s opq))] -> [s -> PwNode s opq] -> PwNode s opq
+  = [(String, s -> PwAttribute s opq)] -> [s -> PwNode s opq] -> (s -> PwNode s opq)
+type Sig s opq = [(String, s -> PwAttribute s opq)] -> [s -> PwNode s opq] -> PwNode s opq
 
 type AFSig_ s opq = [s -> PwNode s opq] -> (s -> PwNode s opq)
 type Sig_ s opq = [s -> PwNode s opq] -> PwNode s opq
@@ -783,2269 +783,2269 @@ 
 
 a :: AFSig s opq
-a x y = (\_ -> PwElement "a" x y)
+a x y _ = PwElement "a" x y
 
 a' :: Sig s opq
 a' = PwElement "a"
 
 a_ :: AFSig_ s opq
-a_ x = (\_ -> PwElement "a" dats x)
+a_ x _ = PwElement "a" dats x
 
 a'_ :: Sig_ s opq
-a'_ x = PwElement "a" dats x
+a'_ = PwElement "a" dats
 
 a__ :: AFSig__ s opq
-a__ x = (\_ -> PwElement "a" dats [txt x])
+a__ x _ = PwElement "a" dats [txt x]
 
 a'__ :: Sig__ s opq
 a'__ x = PwElement "a" dats [txt x]
 
 
 abbr :: AFSig s opq
-abbr x y = (\_ -> PwElement "abbr" x y)
+abbr x y _ = PwElement "abbr" x y
 
 abbr' :: Sig s opq
 abbr' = PwElement "abbr"
 
 abbr_ :: AFSig_ s opq
-abbr_ x = (\_ -> PwElement "abbr" dats x)
+abbr_ x _ = PwElement "abbr" dats x
 
 abbr'_ :: Sig_ s opq
-abbr'_ x = PwElement "abbr" dats x
+abbr'_ = PwElement "abbr" dats
 
 abbr__ :: AFSig__ s opq
-abbr__ x = (\_ -> PwElement "abbr" dats [txt x])
+abbr__ x _ = PwElement "abbr" dats [txt x]
 
 abbr'__ :: Sig__ s opq
 abbr'__ x = PwElement "abbr" dats [txt x]
 
 
 acronym :: AFSig s opq
-acronym x y = (\_ -> PwElement "acronym" x y)
+acronym x y _ = PwElement "acronym" x y
 
 acronym' :: Sig s opq
 acronym' = PwElement "acronym"
 
 acronym_ :: AFSig_ s opq
-acronym_ x = (\_ -> PwElement "acronym" dats x)
+acronym_ x _ = PwElement "acronym" dats x
 
 acronym'_ :: Sig_ s opq
-acronym'_ x = PwElement "acronym" dats x
+acronym'_ = PwElement "acronym" dats
 
 acronym__ :: AFSig__ s opq
-acronym__ x = (\_ -> PwElement "acronym" dats [txt x])
+acronym__ x _ = PwElement "acronym" dats [txt x]
 
 acronym'__ :: Sig__ s opq
 acronym'__ x = PwElement "acronym" dats [txt x]
 
 
 address :: AFSig s opq
-address x y = (\_ -> PwElement "address" x y)
+address x y _ = PwElement "address" x y
 
 address' :: Sig s opq
 address' = PwElement "address"
 
 address_ :: AFSig_ s opq
-address_ x = (\_ -> PwElement "address" dats x)
+address_ x _ = PwElement "address" dats x
 
 address'_ :: Sig_ s opq
-address'_ x = PwElement "address" dats x
+address'_ = PwElement "address" dats
 
 address__ :: AFSig__ s opq
-address__ x = (\_ -> PwElement "address" dats [txt x])
+address__ x _ = PwElement "address" dats [txt x]
 
 address'__ :: Sig__ s opq
 address'__ x = PwElement "address" dats [txt x]
 
 
 applet :: AFSig s opq
-applet x y = (\_ -> PwElement "applet" x y)
+applet x y _ = PwElement "applet" x y
 
 applet' :: Sig s opq
 applet' = PwElement "applet"
 
 applet_ :: AFSig_ s opq
-applet_ x = (\_ -> PwElement "applet" dats x)
+applet_ x _ = PwElement "applet" dats x
 
 applet'_ :: Sig_ s opq
-applet'_ x = PwElement "applet" dats x
+applet'_ = PwElement "applet" dats
 
 applet__ :: AFSig__ s opq
-applet__ x = (\_ -> PwElement "applet" dats [txt x])
+applet__ x _ = PwElement "applet" dats [txt x]
 
 applet'__ :: Sig__ s opq
 applet'__ x = PwElement "applet" dats [txt x]
 
 
 area :: AFSig s opq
-area x y = (\_ -> PwElement "area" x y)
+area x y _ = PwElement "area" x y
 
 area' :: Sig s opq
 area' = PwElement "area"
 
 area_ :: AFSig_ s opq
-area_ x = (\_ -> PwElement "area" dats x)
+area_ x _ = PwElement "area" dats x
 
 area'_ :: Sig_ s opq
-area'_ x = PwElement "area" dats x
+area'_ = PwElement "area" dats
 
 area__ :: AFSig__ s opq
-area__ x = (\_ -> PwElement "area" dats [txt x])
+area__ x _ = PwElement "area" dats [txt x]
 
 area'__ :: Sig__ s opq
 area'__ x = PwElement "area" dats [txt x]
 
 
 article :: AFSig s opq
-article x y = (\_ -> PwElement "article" x y)
+article x y _ = PwElement "article" x y
 
 article' :: Sig s opq
 article' = PwElement "article"
 
 article_ :: AFSig_ s opq
-article_ x = (\_ -> PwElement "article" dats x)
+article_ x _ = PwElement "article" dats x
 
 article'_ :: Sig_ s opq
-article'_ x = PwElement "article" dats x
+article'_ = PwElement "article" dats
 
 article__ :: AFSig__ s opq
-article__ x = (\_ -> PwElement "article" dats [txt x])
+article__ x _ = PwElement "article" dats [txt x]
 
 article'__ :: Sig__ s opq
 article'__ x = PwElement "article" dats [txt x]
 
 
 aside :: AFSig s opq
-aside x y = (\_ -> PwElement "aside" x y)
+aside x y _ = PwElement "aside" x y
 
 aside' :: Sig s opq
 aside' = PwElement "aside"
 
 aside_ :: AFSig_ s opq
-aside_ x = (\_ -> PwElement "aside" dats x)
+aside_ x _ = PwElement "aside" dats x
 
 aside'_ :: Sig_ s opq
-aside'_ x = PwElement "aside" dats x
+aside'_ = PwElement "aside" dats
 
 aside__ :: AFSig__ s opq
-aside__ x = (\_ -> PwElement "aside" dats [txt x])
+aside__ x _ = PwElement "aside" dats [txt x]
 
 aside'__ :: Sig__ s opq
 aside'__ x = PwElement "aside" dats [txt x]
 
 
 audio :: AFSig s opq
-audio x y = (\_ -> PwElement "audio" x y)
+audio x y _ = PwElement "audio" x y
 
 audio' :: Sig s opq
 audio' = PwElement "audio"
 
 audio_ :: AFSig_ s opq
-audio_ x = (\_ -> PwElement "audio" dats x)
+audio_ x _ = PwElement "audio" dats x
 
 audio'_ :: Sig_ s opq
-audio'_ x = PwElement "audio" dats x
+audio'_ = PwElement "audio" dats
 
 audio__ :: AFSig__ s opq
-audio__ x = (\_ -> PwElement "audio" dats [txt x])
+audio__ x _ = PwElement "audio" dats [txt x]
 
 audio'__ :: Sig__ s opq
 audio'__ x = PwElement "audio" dats [txt x]
 
 
 b :: AFSig s opq
-b x y = (\_ -> PwElement "b" x y)
+b x y _ = PwElement "b" x y
 
 b' :: Sig s opq
 b' = PwElement "b"
 
 b_ :: AFSig_ s opq
-b_ x = (\_ -> PwElement "b" dats x)
+b_ x _ = PwElement "b" dats x
 
 b'_ :: Sig_ s opq
-b'_ x = PwElement "b" dats x
+b'_ = PwElement "b" dats
 
 b__ :: AFSig__ s opq
-b__ x = (\_ -> PwElement "b" dats [txt x])
+b__ x _ = PwElement "b" dats [txt x]
 
 b'__ :: Sig__ s opq
 b'__ x = PwElement "b" dats [txt x]
 
 
 base :: AFSig s opq
-base x y = (\_ -> PwElement "base" x y)
+base x y _ = PwElement "base" x y
 
 base' :: Sig s opq
 base' = PwElement "base"
 
 base_ :: AFSig_ s opq
-base_ x = (\_ -> PwElement "base" dats x)
+base_ x _ = PwElement "base" dats x
 
 base'_ :: Sig_ s opq
-base'_ x = PwElement "base" dats x
+base'_ = PwElement "base" dats
 
 base__ :: AFSig__ s opq
-base__ x = (\_ -> PwElement "base" dats [txt x])
+base__ x _ = PwElement "base" dats [txt x]
 
 base'__ :: Sig__ s opq
 base'__ x = PwElement "base" dats [txt x]
 
 
 basefont :: AFSig s opq
-basefont x y = (\_ -> PwElement "basefont" x y)
+basefont x y _ = PwElement "basefont" x y
 
 basefont' :: Sig s opq
 basefont' = PwElement "basefont"
 
 basefont_ :: AFSig_ s opq
-basefont_ x = (\_ -> PwElement "basefont" dats x)
+basefont_ x _ = PwElement "basefont" dats x
 
 basefont'_ :: Sig_ s opq
-basefont'_ x = PwElement "basefont" dats x
+basefont'_ = PwElement "basefont" dats
 
 basefont__ :: AFSig__ s opq
-basefont__ x = (\_ -> PwElement "basefont" dats [txt x])
+basefont__ x _ = PwElement "basefont" dats [txt x]
 
 basefont'__ :: Sig__ s opq
 basefont'__ x = PwElement "basefont" dats [txt x]
 
 
 bdi :: AFSig s opq
-bdi x y = (\_ -> PwElement "bdi" x y)
+bdi x y _ = PwElement "bdi" x y
 
 bdi' :: Sig s opq
 bdi' = PwElement "bdi"
 
 bdi_ :: AFSig_ s opq
-bdi_ x = (\_ -> PwElement "bdi" dats x)
+bdi_ x _ = PwElement "bdi" dats x
 
 bdi'_ :: Sig_ s opq
-bdi'_ x = PwElement "bdi" dats x
+bdi'_ = PwElement "bdi" dats
 
 bdi__ :: AFSig__ s opq
-bdi__ x = (\_ -> PwElement "bdi" dats [txt x])
+bdi__ x _ = PwElement "bdi" dats [txt x]
 
 bdi'__ :: Sig__ s opq
 bdi'__ x = PwElement "bdi" dats [txt x]
 
 
 bdo :: AFSig s opq
-bdo x y = (\_ -> PwElement "bdo" x y)
+bdo x y _ = PwElement "bdo" x y
 
 bdo' :: Sig s opq
 bdo' = PwElement "bdo"
 
 bdo_ :: AFSig_ s opq
-bdo_ x = (\_ -> PwElement "bdo" dats x)
+bdo_ x _ = PwElement "bdo" dats x
 
 bdo'_ :: Sig_ s opq
-bdo'_ x = PwElement "bdo" dats x
+bdo'_ = PwElement "bdo" dats
 
 bdo__ :: AFSig__ s opq
-bdo__ x = (\_ -> PwElement "bdo" dats [txt x])
+bdo__ x _ = PwElement "bdo" dats [txt x]
 
 bdo'__ :: Sig__ s opq
 bdo'__ x = PwElement "bdo" dats [txt x]
 
 
 big :: AFSig s opq
-big x y = (\_ -> PwElement "big" x y)
+big x y _ = PwElement "big" x y
 
 big' :: Sig s opq
 big' = PwElement "big"
 
 big_ :: AFSig_ s opq
-big_ x = (\_ -> PwElement "big" dats x)
+big_ x _ = PwElement "big" dats x
 
 big'_ :: Sig_ s opq
-big'_ x = PwElement "big" dats x
+big'_ = PwElement "big" dats
 
 big__ :: AFSig__ s opq
-big__ x = (\_ -> PwElement "big" dats [txt x])
+big__ x _ = PwElement "big" dats [txt x]
 
 big'__ :: Sig__ s opq
 big'__ x = PwElement "big" dats [txt x]
 
 
 blockquote :: AFSig s opq
-blockquote x y = (\_ -> PwElement "blockquote" x y)
+blockquote x y _ = PwElement "blockquote" x y
 
 blockquote' :: Sig s opq
 blockquote' = PwElement "blockquote"
 
 blockquote_ :: AFSig_ s opq
-blockquote_ x = (\_ -> PwElement "blockquote" dats x)
+blockquote_ x _ = PwElement "blockquote" dats x
 
 blockquote'_ :: Sig_ s opq
-blockquote'_ x = PwElement "blockquote" dats x
+blockquote'_ = PwElement "blockquote" dats
 
 blockquote__ :: AFSig__ s opq
-blockquote__ x = (\_ -> PwElement "blockquote" dats [txt x])
+blockquote__ x _ = PwElement "blockquote" dats [txt x]
 
 blockquote'__ :: Sig__ s opq
 blockquote'__ x = PwElement "blockquote" dats [txt x]
 
 
 body :: AFSig s opq
-body x y = (\_ -> PwElement "body" x y)
+body x y _ = PwElement "body" x y
 
 body' :: Sig s opq
 body' = PwElement "body"
 
 body_ :: AFSig_ s opq
-body_ x = (\_ -> PwElement "body" dats x)
+body_ x _ = PwElement "body" dats x
 
 body'_ :: Sig_ s opq
-body'_ x = PwElement "body" dats x
+body'_ = PwElement "body" dats
 
 body__ :: AFSig__ s opq
-body__ x = (\_ -> PwElement "body" dats [txt x])
+body__ x _ = PwElement "body" dats [txt x]
 
 body'__ :: Sig__ s opq
 body'__ x = PwElement "body" dats [txt x]
 
 
 br :: (s -> PwNode s opq)
-br = (\_ -> PwElement "br" dats [])
+br _ = PwElement "br" dats []
 
 button :: AFSig s opq
-button x y = (\_ -> PwElement "button" x y)
+button x y _ = PwElement "button" x y
 
 button' :: Sig s opq
 button' = PwElement "button"
 
 button_ :: AFSig_ s opq
-button_ x = (\_ -> PwElement "button" dats x)
+button_ x _ = PwElement "button" dats x
 
 button'_ :: Sig_ s opq
-button'_ x = PwElement "button" dats x
+button'_ = PwElement "button" dats
 
 button__ :: AFSig__ s opq
-button__ x = (\_ -> PwElement "button" dats [txt x])
+button__ x _ = PwElement "button" dats [txt x]
 
 button'__ :: Sig__ s opq
 button'__ x = PwElement "button" dats [txt x]
 
 
 canvas :: AFSig s opq
-canvas x y = (\_ -> PwElement "canvas" x y)
+canvas x y _ = PwElement "canvas" x y
 
 canvas' :: Sig s opq
 canvas' = PwElement "canvas"
 
 canvas_ :: AFSig_ s opq
-canvas_ x = (\_ -> PwElement "canvas" dats x)
+canvas_ x _ = PwElement "canvas" dats x
 
 canvas'_ :: Sig_ s opq
-canvas'_ x = PwElement "canvas" dats x
+canvas'_ = PwElement "canvas" dats
 
 canvas__ :: AFSig__ s opq
-canvas__ x = (\_ -> PwElement "canvas" dats [txt x])
+canvas__ x _ = PwElement "canvas" dats [txt x]
 
 canvas'__ :: Sig__ s opq
 canvas'__ x = PwElement "canvas" dats [txt x]
 
 
 caption :: AFSig s opq
-caption x y = (\_ -> PwElement "caption" x y)
+caption x y _ = PwElement "caption" x y
 
 caption' :: Sig s opq
 caption' = PwElement "caption"
 
 caption_ :: AFSig_ s opq
-caption_ x = (\_ -> PwElement "caption" dats x)
+caption_ x _ = PwElement "caption" dats x
 
 caption'_ :: Sig_ s opq
-caption'_ x = PwElement "caption" dats x
+caption'_ = PwElement "caption" dats
 
 caption__ :: AFSig__ s opq
-caption__ x = (\_ -> PwElement "caption" dats [txt x])
+caption__ x _ = PwElement "caption" dats [txt x]
 
 caption'__ :: Sig__ s opq
 caption'__ x = PwElement "caption" dats [txt x]
 
 
 center :: AFSig s opq
-center x y = (\_ -> PwElement "center" x y)
+center x y _ = PwElement "center" x y
 
 center' :: Sig s opq
 center' = PwElement "center"
 
 center_ :: AFSig_ s opq
-center_ x = (\_ -> PwElement "center" dats x)
+center_ x _ = PwElement "center" dats x
 
 center'_ :: Sig_ s opq
-center'_ x = PwElement "center" dats x
+center'_ = PwElement "center" dats
 
 center__ :: AFSig__ s opq
-center__ x = (\_ -> PwElement "center" dats [txt x])
+center__ x _ = PwElement "center" dats [txt x]
 
 center'__ :: Sig__ s opq
 center'__ x = PwElement "center" dats [txt x]
 
 
 cite :: AFSig s opq
-cite x y = (\_ -> PwElement "cite" x y)
+cite x y _ = PwElement "cite" x y
 
 cite' :: Sig s opq
 cite' = PwElement "cite"
 
 cite_ :: AFSig_ s opq
-cite_ x = (\_ -> PwElement "cite" dats x)
+cite_ x _ = PwElement "cite" dats x
 
 cite'_ :: Sig_ s opq
-cite'_ x = PwElement "cite" dats x
+cite'_ = PwElement "cite" dats
 
 cite__ :: AFSig__ s opq
-cite__ x = (\_ -> PwElement "cite" dats [txt x])
+cite__ x _ = PwElement "cite" dats [txt x]
 
 cite'__ :: Sig__ s opq
 cite'__ x = PwElement "cite" dats [txt x]
 
 
 code :: AFSig s opq
-code x y = (\_ -> PwElement "code" x y)
+code x y _ = PwElement "code" x y
 
 code' :: Sig s opq
 code' = PwElement "code"
 
 code_ :: AFSig_ s opq
-code_ x = (\_ -> PwElement "code" dats x)
+code_ x _ = PwElement "code" dats x
 
 code'_ :: Sig_ s opq
-code'_ x = PwElement "code" dats x
+code'_ = PwElement "code" dats
 
 code__ :: AFSig__ s opq
-code__ x = (\_ -> PwElement "code" dats [txt x])
+code__ x _ = PwElement "code" dats [txt x]
 
 code'__ :: Sig__ s opq
 code'__ x = PwElement "code" dats [txt x]
 
 
 col :: AFSig s opq
-col x y = (\_ -> PwElement "col" x y)
+col x y _ = PwElement "col" x y
 
 col' :: Sig s opq
 col' = PwElement "col"
 
 col_ :: AFSig_ s opq
-col_ x = (\_ -> PwElement "col" dats x)
+col_ x _ = PwElement "col" dats x
 
 col'_ :: Sig_ s opq
-col'_ x = PwElement "col" dats x
+col'_ = PwElement "col" dats
 
 col__ :: AFSig__ s opq
-col__ x = (\_ -> PwElement "col" dats [txt x])
+col__ x _ = PwElement "col" dats [txt x]
 
 col'__ :: Sig__ s opq
 col'__ x = PwElement "col" dats [txt x]
 
 
 colgroup :: AFSig s opq
-colgroup x y = (\_ -> PwElement "colgroup" x y)
+colgroup x y _ = PwElement "colgroup" x y
 
 colgroup' :: Sig s opq
 colgroup' = PwElement "colgroup"
 
 colgroup_ :: AFSig_ s opq
-colgroup_ x = (\_ -> PwElement "colgroup" dats x)
+colgroup_ x _ = PwElement "colgroup" dats x
 
 colgroup'_ :: Sig_ s opq
-colgroup'_ x = PwElement "colgroup" dats x
+colgroup'_ = PwElement "colgroup" dats
 
 colgroup__ :: AFSig__ s opq
-colgroup__ x = (\_ -> PwElement "colgroup" dats [txt x])
+colgroup__ x _ = PwElement "colgroup" dats [txt x]
 
 colgroup'__ :: Sig__ s opq
 colgroup'__ x = PwElement "colgroup" dats [txt x]
 
 
 _data :: AFSig s opq
-_data x y = (\_ -> PwElement "_data" x y)
+_data x y _ = PwElement "_data" x y
 
 _data' :: Sig s opq
 _data' = PwElement "_data"
 
 _data_ :: AFSig_ s opq
-_data_ x = (\_ -> PwElement "_data" dats x)
+_data_ x _ = PwElement "_data" dats x
 
 _data'_ :: Sig_ s opq
-_data'_ x = PwElement "_data" dats x
+_data'_ = PwElement "_data" dats
 
 _data__ :: AFSig__ s opq
-_data__ x = (\_ -> PwElement "_data" dats [txt x])
+_data__ x _ = PwElement "_data" dats [txt x]
 
 _data'__ :: Sig__ s opq
 _data'__ x = PwElement "_data" dats [txt x]
 
 
-_datalist :: AFSig s opq
-_datalist x y = (\_ -> PwElement "_datalist" x y)
+datalist :: AFSig s opq
+datalist x y _ = PwElement "datalist" x y
 
-_datalist' :: Sig s opq
-_datalist' = PwElement "_datalist"
+datalist' :: Sig s opq
+datalist' = PwElement "datalist"
 
-_datalist_ :: AFSig_ s opq
-_datalist_ x = (\_ -> PwElement "_datalist" dats x)
+datalist_ :: AFSig_ s opq
+datalist_ x _ = PwElement "datalist" dats x
 
-_datalist'_ :: Sig_ s opq
-_datalist'_ x = PwElement "_datalist" dats x
+datalist'_ :: Sig_ s opq
+datalist'_ = PwElement "datalist" dats
 
-_datalist__ :: AFSig__ s opq
-_datalist__ x = (\_ -> PwElement "_datalist" dats [txt x])
+datalist__ :: AFSig__ s opq
+datalist__ x _ = PwElement "datalist" dats [txt x]
 
-_datalist'__ :: Sig__ s opq
-_datalist'__ x = PwElement "_datalist" dats [txt x]
+datalist'__ :: Sig__ s opq
+datalist'__ x = PwElement "datalist" dats [txt x]
 
 
 dd :: AFSig s opq
-dd x y = (\_ -> PwElement "dd" x y)
+dd x y _ = PwElement "dd" x y
 
 dd' :: Sig s opq
 dd' = PwElement "dd"
 
 dd_ :: AFSig_ s opq
-dd_ x = (\_ -> PwElement "dd" dats x)
+dd_ x _ = PwElement "dd" dats x
 
 dd'_ :: Sig_ s opq
-dd'_ x = PwElement "dd" dats x
+dd'_ = PwElement "dd" dats
 
 dd__ :: AFSig__ s opq
-dd__ x = (\_ -> PwElement "dd" dats [txt x])
+dd__ x _ = PwElement "dd" dats [txt x]
 
 dd'__ :: Sig__ s opq
 dd'__ x = PwElement "dd" dats [txt x]
 
 
 del :: AFSig s opq
-del x y = (\_ -> PwElement "del" x y)
+del x y _ = PwElement "del" x y
 
 del' :: Sig s opq
 del' = PwElement "del"
 
 del_ :: AFSig_ s opq
-del_ x = (\_ -> PwElement "del" dats x)
+del_ x _ = PwElement "del" dats x
 
 del'_ :: Sig_ s opq
-del'_ x = PwElement "del" dats x
+del'_ = PwElement "del" dats
 
 del__ :: AFSig__ s opq
-del__ x = (\_ -> PwElement "del" dats [txt x])
+del__ x _ = PwElement "del" dats [txt x]
 
 del'__ :: Sig__ s opq
 del'__ x = PwElement "del" dats [txt x]
 
 
 details :: AFSig s opq
-details x y = (\_ -> PwElement "details" x y)
+details x y _ = PwElement "details" x y
 
 details' :: Sig s opq
 details' = PwElement "details"
 
 details_ :: AFSig_ s opq
-details_ x = (\_ -> PwElement "details" dats x)
+details_ x _ = PwElement "details" dats x
 
 details'_ :: Sig_ s opq
-details'_ x = PwElement "details" dats x
+details'_ = PwElement "details" dats
 
 details__ :: AFSig__ s opq
-details__ x = (\_ -> PwElement "details" dats [txt x])
+details__ x _ = PwElement "details" dats [txt x]
 
 details'__ :: Sig__ s opq
 details'__ x = PwElement "details" dats [txt x]
 
 
 dfn :: AFSig s opq
-dfn x y = (\_ -> PwElement "dfn" x y)
+dfn x y _ = PwElement "dfn" x y
 
 dfn' :: Sig s opq
 dfn' = PwElement "dfn"
 
 dfn_ :: AFSig_ s opq
-dfn_ x = (\_ -> PwElement "dfn" dats x)
+dfn_ x _ = PwElement "dfn" dats x
 
 dfn'_ :: Sig_ s opq
-dfn'_ x = PwElement "dfn" dats x
+dfn'_ = PwElement "dfn" dats
 
 dfn__ :: AFSig__ s opq
-dfn__ x = (\_ -> PwElement "dfn" dats [txt x])
+dfn__ x _ = PwElement "dfn" dats [txt x]
 
 dfn'__ :: Sig__ s opq
 dfn'__ x = PwElement "dfn" dats [txt x]
 
 
 dialog :: AFSig s opq
-dialog x y = (\_ -> PwElement "dialog" x y)
+dialog x y _ = PwElement "dialog" x y
 
 dialog' :: Sig s opq
 dialog' = PwElement "dialog"
 
 dialog_ :: AFSig_ s opq
-dialog_ x = (\_ -> PwElement "dialog" dats x)
+dialog_ x _ = PwElement "dialog" dats x
 
 dialog'_ :: Sig_ s opq
-dialog'_ x = PwElement "dialog" dats x
+dialog'_ = PwElement "dialog" dats
 
 dialog__ :: AFSig__ s opq
-dialog__ x = (\_ -> PwElement "dialog" dats [txt x])
+dialog__ x _ = PwElement "dialog" dats [txt x]
 
 dialog'__ :: Sig__ s opq
 dialog'__ x = PwElement "dialog" dats [txt x]
 
 
 dir :: AFSig s opq
-dir x y = (\_ -> PwElement "dir" x y)
+dir x y _ = PwElement "dir" x y
 
 dir' :: Sig s opq
 dir' = PwElement "dir"
 
 dir_ :: AFSig_ s opq
-dir_ x = (\_ -> PwElement "dir" dats x)
+dir_ x _ = PwElement "dir" dats x
 
 dir'_ :: Sig_ s opq
-dir'_ x = PwElement "dir" dats x
+dir'_ = PwElement "dir" dats
 
 dir__ :: AFSig__ s opq
-dir__ x = (\_ -> PwElement "dir" dats [txt x])
+dir__ x _ = PwElement "dir" dats [txt x]
 
 dir'__ :: Sig__ s opq
 dir'__ x = PwElement "dir" dats [txt x]
 
 
 div :: AFSig s opq
-div x y = (\_ -> PwElement "div" x y)
+div x y _ = PwElement "div" x y
 
 div' :: Sig s opq
 div' = PwElement "div"
 
 div_ :: AFSig_ s opq
-div_ x = (\_ -> PwElement "div" dats x)
+div_ x _ = PwElement "div" dats x
 
 div'_ :: Sig_ s opq
-div'_ x = PwElement "div" dats x
+div'_ = PwElement "div" dats
 
 div__ :: AFSig__ s opq
-div__ x = (\_ -> PwElement "div" dats [txt x])
+div__ x _ = PwElement "div" dats [txt x]
 
 div'__ :: Sig__ s opq
 div'__ x = PwElement "div" dats [txt x]
 
 
 dl :: AFSig s opq
-dl x y = (\_ -> PwElement "dl" x y)
+dl x y _ = PwElement "dl" x y
 
 dl' :: Sig s opq
 dl' = PwElement "dl"
 
 dl_ :: AFSig_ s opq
-dl_ x = (\_ -> PwElement "dl" dats x)
+dl_ x _ = PwElement "dl" dats x
 
 dl'_ :: Sig_ s opq
-dl'_ x = PwElement "dl" dats x
+dl'_ = PwElement "dl" dats
 
 dl__ :: AFSig__ s opq
-dl__ x = (\_ -> PwElement "dl" dats [txt x])
+dl__ x _ = PwElement "dl" dats [txt x]
 
 dl'__ :: Sig__ s opq
 dl'__ x = PwElement "dl" dats [txt x]
 
 
 dt :: AFSig s opq
-dt x y = (\_ -> PwElement "dt" x y)
+dt x y _ = PwElement "dt" x y
 
 dt' :: Sig s opq
 dt' = PwElement "dt"
 
 dt_ :: AFSig_ s opq
-dt_ x = (\_ -> PwElement "dt" dats x)
+dt_ x _ = PwElement "dt" dats x
 
 dt'_ :: Sig_ s opq
-dt'_ x = PwElement "dt" dats x
+dt'_ = PwElement "dt" dats
 
 dt__ :: AFSig__ s opq
-dt__ x = (\_ -> PwElement "dt" dats [txt x])
+dt__ x _ = PwElement "dt" dats [txt x]
 
 dt'__ :: Sig__ s opq
 dt'__ x = PwElement "dt" dats [txt x]
 
 
 em :: AFSig s opq
-em x y = (\_ -> PwElement "em" x y)
+em x y _ = PwElement "em" x y
 
 em' :: Sig s opq
 em' = PwElement "em"
 
 em_ :: AFSig_ s opq
-em_ x = (\_ -> PwElement "em" dats x)
+em_ x _ = PwElement "em" dats x
 
 em'_ :: Sig_ s opq
-em'_ x = PwElement "em" dats x
+em'_ = PwElement "em" dats
 
 em__ :: AFSig__ s opq
-em__ x = (\_ -> PwElement "em" dats [txt x])
+em__ x _ = PwElement "em" dats [txt x]
 
 em'__ :: Sig__ s opq
 em'__ x = PwElement "em" dats [txt x]
 
 
 embed :: AFSig s opq
-embed x y = (\_ -> PwElement "embed" x y)
+embed x y _ = PwElement "embed" x y
 
 embed' :: Sig s opq
 embed' = PwElement "embed"
 
 embed_ :: AFSig_ s opq
-embed_ x = (\_ -> PwElement "embed" dats x)
+embed_ x _ = PwElement "embed" dats x
 
 embed'_ :: Sig_ s opq
-embed'_ x = PwElement "embed" dats x
+embed'_ = PwElement "embed" dats
 
 embed__ :: AFSig__ s opq
-embed__ x = (\_ -> PwElement "embed" dats [txt x])
+embed__ x _ = PwElement "embed" dats [txt x]
 
 embed'__ :: Sig__ s opq
 embed'__ x = PwElement "embed" dats [txt x]
 
 
 fieldset :: AFSig s opq
-fieldset x y = (\_ -> PwElement "fieldset" x y)
+fieldset x y _ = PwElement "fieldset" x y
 
 fieldset' :: Sig s opq
 fieldset' = PwElement "fieldset"
 
 fieldset_ :: AFSig_ s opq
-fieldset_ x = (\_ -> PwElement "fieldset" dats x)
+fieldset_ x _ = PwElement "fieldset" dats x
 
 fieldset'_ :: Sig_ s opq
-fieldset'_ x = PwElement "fieldset" dats x
+fieldset'_ = PwElement "fieldset" dats
 
 fieldset__ :: AFSig__ s opq
-fieldset__ x = (\_ -> PwElement "fieldset" dats [txt x])
+fieldset__ x _ = PwElement "fieldset" dats [txt x]
 
 fieldset'__ :: Sig__ s opq
 fieldset'__ x = PwElement "fieldset" dats [txt x]
 
 
 figcaption :: AFSig s opq
-figcaption x y = (\_ -> PwElement "figcaption" x y)
+figcaption x y _ = PwElement "figcaption" x y
 
 figcaption' :: Sig s opq
 figcaption' = PwElement "figcaption"
 
 figcaption_ :: AFSig_ s opq
-figcaption_ x = (\_ -> PwElement "figcaption" dats x)
+figcaption_ x _ = PwElement "figcaption" dats x
 
 figcaption'_ :: Sig_ s opq
-figcaption'_ x = PwElement "figcaption" dats x
+figcaption'_ = PwElement "figcaption" dats
 
 figcaption__ :: AFSig__ s opq
-figcaption__ x = (\_ -> PwElement "figcaption" dats [txt x])
+figcaption__ x _ = PwElement "figcaption" dats [txt x]
 
 figcaption'__ :: Sig__ s opq
 figcaption'__ x = PwElement "figcaption" dats [txt x]
 
 
 figure :: AFSig s opq
-figure x y = (\_ -> PwElement "figure" x y)
+figure x y _ = PwElement "figure" x y
 
 figure' :: Sig s opq
 figure' = PwElement "figure"
 
 figure_ :: AFSig_ s opq
-figure_ x = (\_ -> PwElement "figure" dats x)
+figure_ x _ = PwElement "figure" dats x
 
 figure'_ :: Sig_ s opq
-figure'_ x = PwElement "figure" dats x
+figure'_ = PwElement "figure" dats
 
 figure__ :: AFSig__ s opq
-figure__ x = (\_ -> PwElement "figure" dats [txt x])
+figure__ x _ = PwElement "figure" dats [txt x]
 
 figure'__ :: Sig__ s opq
 figure'__ x = PwElement "figure" dats [txt x]
 
 
 font :: AFSig s opq
-font x y = (\_ -> PwElement "font" x y)
+font x y _ = PwElement "font" x y
 
 font' :: Sig s opq
 font' = PwElement "font"
 
 font_ :: AFSig_ s opq
-font_ x = (\_ -> PwElement "font" dats x)
+font_ x _ = PwElement "font" dats x
 
 font'_ :: Sig_ s opq
-font'_ x = PwElement "font" dats x
+font'_ = PwElement "font" dats
 
 font__ :: AFSig__ s opq
-font__ x = (\_ -> PwElement "font" dats [txt x])
+font__ x _ = PwElement "font" dats [txt x]
 
 font'__ :: Sig__ s opq
 font'__ x = PwElement "font" dats [txt x]
 
 
 footer :: AFSig s opq
-footer x y = (\_ -> PwElement "footer" x y)
+footer x y _ = PwElement "footer" x y
 
 footer' :: Sig s opq
 footer' = PwElement "footer"
 
 footer_ :: AFSig_ s opq
-footer_ x = (\_ -> PwElement "footer" dats x)
+footer_ x _ = PwElement "footer" dats x
 
 footer'_ :: Sig_ s opq
-footer'_ x = PwElement "footer" dats x
+footer'_ = PwElement "footer" dats
 
 footer__ :: AFSig__ s opq
-footer__ x = (\_ -> PwElement "footer" dats [txt x])
+footer__ x _ = PwElement "footer" dats [txt x]
 
 footer'__ :: Sig__ s opq
 footer'__ x = PwElement "footer" dats [txt x]
 
 
 form :: AFSig s opq
-form x y = (\_ -> PwElement "form" x y)
+form x y _ = PwElement "form" x y
 
 form' :: Sig s opq
 form' = PwElement "form"
 
 form_ :: AFSig_ s opq
-form_ x = (\_ -> PwElement "form" dats x)
+form_ x _ = PwElement "form" dats x
 
 form'_ :: Sig_ s opq
-form'_ x = PwElement "form" dats x
+form'_ = PwElement "form" dats
 
 form__ :: AFSig__ s opq
-form__ x = (\_ -> PwElement "form" dats [txt x])
+form__ x _ = PwElement "form" dats [txt x]
 
 form'__ :: Sig__ s opq
 form'__ x = PwElement "form" dats [txt x]
 
 
 frame :: AFSig s opq
-frame x y = (\_ -> PwElement "frame" x y)
+frame x y _ = PwElement "frame" x y
 
 frame' :: Sig s opq
 frame' = PwElement "frame"
 
 frame_ :: AFSig_ s opq
-frame_ x = (\_ -> PwElement "frame" dats x)
+frame_ x _ = PwElement "frame" dats x
 
 frame'_ :: Sig_ s opq
-frame'_ x = PwElement "frame" dats x
+frame'_ = PwElement "frame" dats
 
 frame__ :: AFSig__ s opq
-frame__ x = (\_ -> PwElement "frame" dats [txt x])
+frame__ x _ = PwElement "frame" dats [txt x]
 
 frame'__ :: Sig__ s opq
 frame'__ x = PwElement "frame" dats [txt x]
 
 
 frameset :: AFSig s opq
-frameset x y = (\_ -> PwElement "frameset" x y)
+frameset x y _ = PwElement "frameset" x y
 
 frameset' :: Sig s opq
 frameset' = PwElement "frameset"
 
 frameset_ :: AFSig_ s opq
-frameset_ x = (\_ -> PwElement "frameset" dats x)
+frameset_ x _ = PwElement "frameset" dats x
 
 frameset'_ :: Sig_ s opq
-frameset'_ x = PwElement "frameset" dats x
+frameset'_ = PwElement "frameset" dats
 
 frameset__ :: AFSig__ s opq
-frameset__ x = (\_ -> PwElement "frameset" dats [txt x])
+frameset__ x _ = PwElement "frameset" dats [txt x]
 
 frameset'__ :: Sig__ s opq
 frameset'__ x = PwElement "frameset" dats [txt x]
 
 head :: AFSig s opq
-head x y = (\_ -> PwElement "head" x y)
+head x y _ = PwElement "head" x y
 
 head' :: Sig s opq
 head' = PwElement "head"
 
 head_ :: AFSig_ s opq
-head_ x = (\_ -> PwElement "head" dats x)
+head_ x _ = PwElement "head" dats x
 
 head'_ :: Sig_ s opq
-head'_ x = PwElement "head" dats x
+head'_ = PwElement "head" dats
 
 head__ :: AFSig__ s opq
-head__ x = (\_ -> PwElement "head" dats [txt x])
+head__ x _ = PwElement "head" dats [txt x]
 
 head'__ :: Sig__ s opq
 head'__ x = PwElement "head" dats [txt x]
 
 
 header :: AFSig s opq
-header x y = (\_ -> PwElement "header" x y)
+header x y _ = PwElement "header" x y
 
 header' :: Sig s opq
 header' = PwElement "header"
 
 header_ :: AFSig_ s opq
-header_ x = (\_ -> PwElement "header" dats x)
+header_ x _ = PwElement "header" dats x
 
 header'_ :: Sig_ s opq
-header'_ x = PwElement "header" dats x
+header'_ = PwElement "header" dats
 
 header__ :: AFSig__ s opq
-header__ x = (\_ -> PwElement "header" dats [txt x])
+header__ x _ = PwElement "header" dats [txt x]
 
 header'__ :: Sig__ s opq
 header'__ x = PwElement "header" dats [txt x]
 
 
 hr :: (s -> PwNode s opq)
-hr = (\_ -> PwElement "br" dats [])
+hr _ = PwElement "br" dats []
 
 html :: AFSig s opq
-html x y = (\_ -> PwElement "html" x y)
+html x y _ = PwElement "html" x y
 
 html' :: Sig s opq
 html' = PwElement "html"
 
 html_ :: AFSig_ s opq
-html_ x = (\_ -> PwElement "html" dats x)
+html_ x _ = PwElement "html" dats x
 
 html'_ :: Sig_ s opq
-html'_ x = PwElement "html" dats x
+html'_ = PwElement "html" dats
 
 html__ :: AFSig__ s opq
-html__ x = (\_ -> PwElement "html" dats [txt x])
+html__ x _ = PwElement "html" dats [txt x]
 
 html'__ :: Sig__ s opq
 html'__ x = PwElement "html" dats [txt x]
 
 
 i :: AFSig s opq
-i x y = (\_ -> PwElement "i" x y)
+i x y _ = PwElement "i" x y
 
 i' :: Sig s opq
 i' = PwElement "i"
 
 i_ :: AFSig_ s opq
-i_ x = (\_ -> PwElement "i" dats x)
+i_ x _ = PwElement "i" dats x
 
 i'_ :: Sig_ s opq
-i'_ x = PwElement "i" dats x
+i'_ = PwElement "i" dats
 
 i__ :: AFSig__ s opq
-i__ x = (\_ -> PwElement "i" dats [txt x])
+i__ x _ = PwElement "i" dats [txt x]
 
 i'__ :: Sig__ s opq
 i'__ x = PwElement "i" dats [txt x]
 
 
 iframe :: AFSig s opq
-iframe x y = (\_ -> PwElement "iframe" x y)
+iframe x y _ = PwElement "iframe" x y
 
 iframe' :: Sig s opq
 iframe' = PwElement "iframe"
 
 iframe_ :: AFSig_ s opq
-iframe_ x = (\_ -> PwElement "iframe" dats x)
+iframe_ x _ = PwElement "iframe" dats x
 
 iframe'_ :: Sig_ s opq
-iframe'_ x = PwElement "iframe" dats x
+iframe'_ = PwElement "iframe" dats
 
 iframe__ :: AFSig__ s opq
-iframe__ x = (\_ -> PwElement "iframe" dats [txt x])
+iframe__ x _ = PwElement "iframe" dats [txt x]
 
 iframe'__ :: Sig__ s opq
 iframe'__ x = PwElement "iframe" dats [txt x]
 
 
-img :: [(String, (s -> PwAttribute s opq))] -> (s -> PwNode s opq)
-img x = (\_ -> PwElement "img" x [])
+img :: [(String, s -> PwAttribute s opq)] -> (s -> PwNode s opq)
+img x _ = PwElement "img" x []
 
-img' :: [(String, (s -> PwAttribute s opq))] -> PwNode s opq
+img' :: [(String, s -> PwAttribute s opq)] -> PwNode s opq
 img' x = PwElement "img" x []
 
 img_ :: (s -> PwNode s opq)
-img_ = (\_ -> PwElement "img" dats [])
+img_ _ = PwElement "img" dats []
 
 img'_ :: PwNode s opq
 img'_ = PwElement "img" dats []
 
 input :: AFSig s opq
-input x y = (\_ -> PwElement "input" x y)
+input x y _ = PwElement "input" x y
 
 input' :: Sig s opq
 input' = PwElement "input"
 
 input_ :: AFSig_ s opq
-input_ x = (\_ -> PwElement "input" dats x)
+input_ x _ = PwElement "input" dats x
 
 input'_ :: Sig_ s opq
-input'_ x = PwElement "input" dats x
+input'_ = PwElement "input" dats
 
 input__ :: AFSig__ s opq
-input__ x = (\_ -> PwElement "input" dats [txt x])
+input__ x _ = PwElement "input" dats [txt x]
 
 input'__ :: Sig__ s opq
 input'__ x = PwElement "input" dats [txt x]
 
 
 ins :: AFSig s opq
-ins x y = (\_ -> PwElement "ins" x y)
+ins x y _ = PwElement "ins" x y
 
 ins' :: Sig s opq
 ins' = PwElement "ins"
 
 ins_ :: AFSig_ s opq
-ins_ x = (\_ -> PwElement "ins" dats x)
+ins_ x _ = PwElement "ins" dats x
 
 ins'_ :: Sig_ s opq
-ins'_ x = PwElement "ins" dats x
+ins'_ = PwElement "ins" dats
 
 ins__ :: AFSig__ s opq
-ins__ x = (\_ -> PwElement "ins" dats [txt x])
+ins__ x _ = PwElement "ins" dats [txt x]
 
 ins'__ :: Sig__ s opq
 ins'__ x = PwElement "ins" dats [txt x]
 
 
 kbd :: AFSig s opq
-kbd x y = (\_ -> PwElement "kbd" x y)
+kbd x y _ = PwElement "kbd" x y
 
 kbd' :: Sig s opq
 kbd' = PwElement "kbd"
 
 kbd_ :: AFSig_ s opq
-kbd_ x = (\_ -> PwElement "kbd" dats x)
+kbd_ x _ = PwElement "kbd" dats x
 
 kbd'_ :: Sig_ s opq
-kbd'_ x = PwElement "kbd" dats x
+kbd'_ = PwElement "kbd" dats
 
 kbd__ :: AFSig__ s opq
-kbd__ x = (\_ -> PwElement "kbd" dats [txt x])
+kbd__ x _ = PwElement "kbd" dats [txt x]
 
 kbd'__ :: Sig__ s opq
 kbd'__ x = PwElement "kbd" dats [txt x]
 
 
 label :: AFSig s opq
-label x y = (\_ -> PwElement "label" x y)
+label x y _ = PwElement "label" x y
 
 label' :: Sig s opq
 label' = PwElement "label"
 
 label_ :: AFSig_ s opq
-label_ x = (\_ -> PwElement "label" dats x)
+label_ x _ = PwElement "label" dats x
 
 label'_ :: Sig_ s opq
-label'_ x = PwElement "label" dats x
+label'_ = PwElement "label" dats
 
 label__ :: AFSig__ s opq
-label__ x = (\_ -> PwElement "label" dats [txt x])
+label__ x _ = PwElement "label" dats [txt x]
 
 label'__ :: Sig__ s opq
 label'__ x = PwElement "label" dats [txt x]
 
 
 legend :: AFSig s opq
-legend x y = (\_ -> PwElement "legend" x y)
+legend x y _ = PwElement "legend" x y
 
 legend' :: Sig s opq
 legend' = PwElement "legend"
 
 legend_ :: AFSig_ s opq
-legend_ x = (\_ -> PwElement "legend" dats x)
+legend_ x _ = PwElement "legend" dats x
 
 legend'_ :: Sig_ s opq
-legend'_ x = PwElement "legend" dats x
+legend'_ = PwElement "legend" dats
 
 legend__ :: AFSig__ s opq
-legend__ x = (\_ -> PwElement "legend" dats [txt x])
+legend__ x _ = PwElement "legend" dats [txt x]
 
 legend'__ :: Sig__ s opq
 legend'__ x = PwElement "legend" dats [txt x]
 
 
 li :: AFSig s opq
-li x y = (\_ -> PwElement "li" x y)
+li x y _ = PwElement "li" x y
 
 li' :: Sig s opq
 li' = PwElement "li"
 
 li_ :: AFSig_ s opq
-li_ x = (\_ -> PwElement "li" dats x)
+li_ x _ = PwElement "li" dats x
 
 li'_ :: Sig_ s opq
-li'_ x = PwElement "li" dats x
+li'_ = PwElement "li" dats
 
 li__ :: AFSig__ s opq
-li__ x = (\_ -> PwElement "li" dats [txt x])
+li__ x _ = PwElement "li" dats [txt x]
 
 li'__ :: Sig__ s opq
 li'__ x = PwElement "li" dats [txt x]
 
 
 link :: AFSig s opq
-link x y = (\_ -> PwElement "link" x y)
+link x y _ = PwElement "link" x y
 
 link' :: Sig s opq
 link' = PwElement "link"
 
 link_ :: AFSig_ s opq
-link_ x = (\_ -> PwElement "link" dats x)
+link_ x _ = PwElement "link" dats x
 
 link'_ :: Sig_ s opq
-link'_ x = PwElement "link" dats x
+link'_ = PwElement "link" dats
 
 link__ :: AFSig__ s opq
-link__ x = (\_ -> PwElement "link" dats [txt x])
+link__ x _ = PwElement "link" dats [txt x]
 
 link'__ :: Sig__ s opq
 link'__ x = PwElement "link" dats [txt x]
 
 
 main :: AFSig s opq
-main x y = (\_ -> PwElement "main" x y)
+main x y _ = PwElement "main" x y
 
 main' :: Sig s opq
 main' = PwElement "main"
 
 main_ :: AFSig_ s opq
-main_ x = (\_ -> PwElement "main" dats x)
+main_ x _ = PwElement "main" dats x
 
 main'_ :: Sig_ s opq
-main'_ x = PwElement "main" dats x
+main'_ = PwElement "main" dats
 
 main__ :: AFSig__ s opq
-main__ x = (\_ -> PwElement "main" dats [txt x])
+main__ x _ = PwElement "main" dats [txt x]
 
 main'__ :: Sig__ s opq
 main'__ x = PwElement "main" dats [txt x]
 
 
 map :: AFSig s opq
-map x y = (\_ -> PwElement "map" x y)
+map x y _ = PwElement "map" x y
 
 map' :: Sig s opq
 map' = PwElement "map"
 
 map_ :: AFSig_ s opq
-map_ x = (\_ -> PwElement "map" dats x)
+map_ x _ = PwElement "map" dats x
 
 map'_ :: Sig_ s opq
-map'_ x = PwElement "map" dats x
+map'_ = PwElement "map" dats
 
 map__ :: AFSig__ s opq
-map__ x = (\_ -> PwElement "map" dats [txt x])
+map__ x _ = PwElement "map" dats [txt x]
 
 map'__ :: Sig__ s opq
 map'__ x = PwElement "map" dats [txt x]
 
 
 mark :: AFSig s opq
-mark x y = (\_ -> PwElement "mark" x y)
+mark x y _ = PwElement "mark" x y
 
 mark' :: Sig s opq
 mark' = PwElement "mark"
 
 mark_ :: AFSig_ s opq
-mark_ x = (\_ -> PwElement "mark" dats x)
+mark_ x _ = PwElement "mark" dats x
 
 mark'_ :: Sig_ s opq
-mark'_ x = PwElement "mark" dats x
+mark'_ = PwElement "mark" dats
 
 mark__ :: AFSig__ s opq
-mark__ x = (\_ -> PwElement "mark" dats [txt x])
+mark__ x _ = PwElement "mark" dats [txt x]
 
 mark'__ :: Sig__ s opq
 mark'__ x = PwElement "mark" dats [txt x]
 
 
 meta :: AFSig s opq
-meta x y = (\_ -> PwElement "meta" x y)
+meta x y _ = PwElement "meta" x y
 
 meta' :: Sig s opq
 meta' = PwElement "meta"
 
 meta_ :: AFSig_ s opq
-meta_ x = (\_ -> PwElement "meta" dats x)
+meta_ x _ = PwElement "meta" dats x
 
 meta'_ :: Sig_ s opq
-meta'_ x = PwElement "meta" dats x
+meta'_ = PwElement "meta" dats
 
 meta__ :: AFSig__ s opq
-meta__ x = (\_ -> PwElement "meta" dats [txt x])
+meta__ x _ = PwElement "meta" dats [txt x]
 
 meta'__ :: Sig__ s opq
 meta'__ x = PwElement "meta" dats [txt x]
 
 
 meter :: AFSig s opq
-meter x y = (\_ -> PwElement "meter" x y)
+meter x y _ = PwElement "meter" x y
 
 meter' :: Sig s opq
 meter' = PwElement "meter"
 
 meter_ :: AFSig_ s opq
-meter_ x = (\_ -> PwElement "meter" dats x)
+meter_ x _ = PwElement "meter" dats x
 
 meter'_ :: Sig_ s opq
-meter'_ x = PwElement "meter" dats x
+meter'_ = PwElement "meter" dats
 
 meter__ :: AFSig__ s opq
-meter__ x = (\_ -> PwElement "meter" dats [txt x])
+meter__ x _ = PwElement "meter" dats [txt x]
 
 meter'__ :: Sig__ s opq
 meter'__ x = PwElement "meter" dats [txt x]
 
 
 nav :: AFSig s opq
-nav x y = (\_ -> PwElement "nav" x y)
+nav x y _ = PwElement "nav" x y
 
 nav' :: Sig s opq
 nav' = PwElement "nav"
 
 nav_ :: AFSig_ s opq
-nav_ x = (\_ -> PwElement "nav" dats x)
+nav_ x _ = PwElement "nav" dats x
 
 nav'_ :: Sig_ s opq
-nav'_ x = PwElement "nav" dats x
+nav'_ = PwElement "nav" dats
 
 nav__ :: AFSig__ s opq
-nav__ x = (\_ -> PwElement "nav" dats [txt x])
+nav__ x _ = PwElement "nav" dats [txt x]
 
 nav'__ :: Sig__ s opq
 nav'__ x = PwElement "nav" dats [txt x]
 
 
 noframes :: AFSig s opq
-noframes x y = (\_ -> PwElement "noframes" x y)
+noframes x y _ = PwElement "noframes" x y
 
 noframes' :: Sig s opq
 noframes' = PwElement "noframes"
 
 noframes_ :: AFSig_ s opq
-noframes_ x = (\_ -> PwElement "noframes" dats x)
+noframes_ x _ = PwElement "noframes" dats x
 
 noframes'_ :: Sig_ s opq
-noframes'_ x = PwElement "noframes" dats x
+noframes'_ = PwElement "noframes" dats
 
 noframes__ :: AFSig__ s opq
-noframes__ x = (\_ -> PwElement "noframes" dats [txt x])
+noframes__ x _ = PwElement "noframes" dats [txt x]
 
 noframes'__ :: Sig__ s opq
 noframes'__ x = PwElement "noframes" dats [txt x]
 
 
 noscript :: AFSig s opq
-noscript x y = (\_ -> PwElement "noscript" x y)
+noscript x y _ = PwElement "noscript" x y
 
 noscript' :: Sig s opq
 noscript' = PwElement "noscript"
 
 noscript_ :: AFSig_ s opq
-noscript_ x = (\_ -> PwElement "noscript" dats x)
+noscript_ x _ = PwElement "noscript" dats x
 
 noscript'_ :: Sig_ s opq
-noscript'_ x = PwElement "noscript" dats x
+noscript'_ = PwElement "noscript" dats
 
 noscript__ :: AFSig__ s opq
-noscript__ x = (\_ -> PwElement "noscript" dats [txt x])
+noscript__ x _ = PwElement "noscript" dats [txt x]
 
 noscript'__ :: Sig__ s opq
 noscript'__ x = PwElement "noscript" dats [txt x]
 
 
 object :: AFSig s opq
-object x y = (\_ -> PwElement "object" x y)
+object x y _ = PwElement "object" x y
 
 object' :: Sig s opq
 object' = PwElement "object"
 
 object_ :: AFSig_ s opq
-object_ x = (\_ -> PwElement "object" dats x)
+object_ x _ = PwElement "object" dats x
 
 object'_ :: Sig_ s opq
-object'_ x = PwElement "object" dats x
+object'_ = PwElement "object" dats
 
 object__ :: AFSig__ s opq
-object__ x = (\_ -> PwElement "object" dats [txt x])
+object__ x _ = PwElement "object" dats [txt x]
 
 object'__ :: Sig__ s opq
 object'__ x = PwElement "object" dats [txt x]
 
 
 ol :: AFSig s opq
-ol x y = (\_ -> PwElement "ol" x y)
+ol x y _ = PwElement "ol" x y
 
 ol' :: Sig s opq
 ol' = PwElement "ol"
 
 ol_ :: AFSig_ s opq
-ol_ x = (\_ -> PwElement "ol" dats x)
+ol_ x _ = PwElement "ol" dats x
 
 ol'_ :: Sig_ s opq
-ol'_ x = PwElement "ol" dats x
+ol'_ = PwElement "ol" dats
 
 ol__ :: AFSig__ s opq
-ol__ x = (\_ -> PwElement "ol" dats [txt x])
+ol__ x _ = PwElement "ol" dats [txt x]
 
 ol'__ :: Sig__ s opq
 ol'__ x = PwElement "ol" dats [txt x]
 
 
 optgroup :: AFSig s opq
-optgroup x y = (\_ -> PwElement "optgroup" x y)
+optgroup x y _ = PwElement "optgroup" x y
 
 optgroup' :: Sig s opq
 optgroup' = PwElement "optgroup"
 
 optgroup_ :: AFSig_ s opq
-optgroup_ x = (\_ -> PwElement "optgroup" dats x)
+optgroup_ x _ = PwElement "optgroup" dats x
 
 optgroup'_ :: Sig_ s opq
-optgroup'_ x = PwElement "optgroup" dats x
+optgroup'_ = PwElement "optgroup" dats
 
 optgroup__ :: AFSig__ s opq
-optgroup__ x = (\_ -> PwElement "optgroup" dats [txt x])
+optgroup__ x _ = PwElement "optgroup" dats [txt x]
 
 optgroup'__ :: Sig__ s opq
 optgroup'__ x = PwElement "optgroup" dats [txt x]
 
 
 option :: AFSig s opq
-option x y = (\_ -> PwElement "option" x y)
+option x y _ = PwElement "option" x y
 
 option' :: Sig s opq
 option' = PwElement "option"
 
 option_ :: AFSig_ s opq
-option_ x = (\_ -> PwElement "option" dats x)
+option_ x _ = PwElement "option" dats x
 
 option'_ :: Sig_ s opq
-option'_ x = PwElement "option" dats x
+option'_ = PwElement "option" dats
 
 option__ :: AFSig__ s opq
-option__ x = (\_ -> PwElement "option" dats [txt x])
+option__ x _ = PwElement "option" dats [txt x]
 
 option'__ :: Sig__ s opq
 option'__ x = PwElement "option" dats [txt x]
 
 
 output :: AFSig s opq
-output x y = (\_ -> PwElement "output" x y)
+output x y _ = PwElement "output" x y
 
 output' :: Sig s opq
 output' = PwElement "output"
 
 output_ :: AFSig_ s opq
-output_ x = (\_ -> PwElement "output" dats x)
+output_ x _ = PwElement "output" dats x
 
 output'_ :: Sig_ s opq
-output'_ x = PwElement "output" dats x
+output'_ = PwElement "output" dats
 
 output__ :: AFSig__ s opq
-output__ x = (\_ -> PwElement "output" dats [txt x])
+output__ x _ = PwElement "output" dats [txt x]
 
 output'__ :: Sig__ s opq
 output'__ x = PwElement "output" dats [txt x]
 
 
 p :: AFSig s opq
-p x y = (\_ -> PwElement "p" x y)
+p x y _ = PwElement "p" x y
 
 p' :: Sig s opq
 p' = PwElement "p"
 
 p_ :: AFSig_ s opq
-p_ x = (\_ -> PwElement "p" dats x)
+p_ x _ = PwElement "p" dats x
 
 p'_ :: Sig_ s opq
-p'_ x = PwElement "p" dats x
+p'_ = PwElement "p" dats
 
 p__ :: AFSig__ s opq
-p__ x = (\_ -> PwElement "p" dats [txt x])
+p__ x _ = PwElement "p" dats [txt x]
 
 p'__ :: Sig__ s opq
 p'__ x = PwElement "p" dats [txt x]
 
 
 param :: AFSig s opq
-param x y = (\_ -> PwElement "param" x y)
+param x y _ = PwElement "param" x y
 
 param' :: Sig s opq
 param' = PwElement "param"
 
 param_ :: AFSig_ s opq
-param_ x = (\_ -> PwElement "param" dats x)
+param_ x _ = PwElement "param" dats x
 
 param'_ :: Sig_ s opq
-param'_ x = PwElement "param" dats x
+param'_ = PwElement "param" dats
 
 param__ :: AFSig__ s opq
-param__ x = (\_ -> PwElement "param" dats [txt x])
+param__ x _ = PwElement "param" dats [txt x]
 
 param'__ :: Sig__ s opq
 param'__ x = PwElement "param" dats [txt x]
 
 
 picture :: AFSig s opq
-picture x y = (\_ -> PwElement "picture" x y)
+picture x y _ = PwElement "picture" x y
 
 picture' :: Sig s opq
 picture' = PwElement "picture"
 
 picture_ :: AFSig_ s opq
-picture_ x = (\_ -> PwElement "picture" dats x)
+picture_ x _ = PwElement "picture" dats x
 
 picture'_ :: Sig_ s opq
-picture'_ x = PwElement "picture" dats x
+picture'_ = PwElement "picture" dats
 
 picture__ :: AFSig__ s opq
-picture__ x = (\_ -> PwElement "picture" dats [txt x])
+picture__ x _ = PwElement "picture" dats [txt x]
 
 picture'__ :: Sig__ s opq
 picture'__ x = PwElement "picture" dats [txt x]
 
 
 pre :: AFSig s opq
-pre x y = (\_ -> PwElement "pre" x y)
+pre x y _ = PwElement "pre" x y
 
 pre' :: Sig s opq
 pre' = PwElement "pre"
 
 pre_ :: AFSig_ s opq
-pre_ x = (\_ -> PwElement "pre" dats x)
+pre_ x _ = PwElement "pre" dats x
 
 pre'_ :: Sig_ s opq
-pre'_ x = PwElement "pre" dats x
+pre'_ = PwElement "pre" dats
 
 pre__ :: AFSig__ s opq
-pre__ x = (\_ -> PwElement "pre" dats [txt x])
+pre__ x _ = PwElement "pre" dats [txt x]
 
 pre'__ :: Sig__ s opq
 pre'__ x = PwElement "pre" dats [txt x]
 
 
 progress :: AFSig s opq
-progress x y = (\_ -> PwElement "progress" x y)
+progress x y _ = PwElement "progress" x y
 
 progress' :: Sig s opq
 progress' = PwElement "progress"
 
 progress_ :: AFSig_ s opq
-progress_ x = (\_ -> PwElement "progress" dats x)
+progress_ x _ = PwElement "progress" dats x
 
 progress'_ :: Sig_ s opq
-progress'_ x = PwElement "progress" dats x
+progress'_ = PwElement "progress" dats
 
 progress__ :: AFSig__ s opq
-progress__ x = (\_ -> PwElement "progress" dats [txt x])
+progress__ x _ = PwElement "progress" dats [txt x]
 
 progress'__ :: Sig__ s opq
 progress'__ x = PwElement "progress" dats [txt x]
 
 
 q :: AFSig s opq
-q x y = (\_ -> PwElement "q" x y)
+q x y _ = PwElement "q" x y
 
 q' :: Sig s opq
 q' = PwElement "q"
 
 q_ :: AFSig_ s opq
-q_ x = (\_ -> PwElement "q" dats x)
+q_ x _ = PwElement "q" dats x
 
 q'_ :: Sig_ s opq
-q'_ x = PwElement "q" dats x
+q'_ = PwElement "q" dats
 
 q__ :: AFSig__ s opq
-q__ x = (\_ -> PwElement "q" dats [txt x])
+q__ x _ = PwElement "q" dats [txt x]
 
 q'__ :: Sig__ s opq
 q'__ x = PwElement "q" dats [txt x]
 
 
 rp :: AFSig s opq
-rp x y = (\_ -> PwElement "rp" x y)
+rp x y _ = PwElement "rp" x y
 
 rp' :: Sig s opq
 rp' = PwElement "rp"
 
 rp_ :: AFSig_ s opq
-rp_ x = (\_ -> PwElement "rp" dats x)
+rp_ x _ = PwElement "rp" dats x
 
 rp'_ :: Sig_ s opq
-rp'_ x = PwElement "rp" dats x
+rp'_ = PwElement "rp" dats
 
 rp__ :: AFSig__ s opq
-rp__ x = (\_ -> PwElement "rp" dats [txt x])
+rp__ x _ = PwElement "rp" dats [txt x]
 
 rp'__ :: Sig__ s opq
 rp'__ x = PwElement "rp" dats [txt x]
 
 
 rt :: AFSig s opq
-rt x y = (\_ -> PwElement "rt" x y)
+rt x y _ = PwElement "rt" x y
 
 rt' :: Sig s opq
 rt' = PwElement "rt"
 
 rt_ :: AFSig_ s opq
-rt_ x = (\_ -> PwElement "rt" dats x)
+rt_ x _ = PwElement "rt" dats x
 
 rt'_ :: Sig_ s opq
-rt'_ x = PwElement "rt" dats x
+rt'_ = PwElement "rt" dats
 
 rt__ :: AFSig__ s opq
-rt__ x = (\_ -> PwElement "rt" dats [txt x])
+rt__ x _ = PwElement "rt" dats [txt x]
 
 rt'__ :: Sig__ s opq
 rt'__ x = PwElement "rt" dats [txt x]
 
 
 ruby :: AFSig s opq
-ruby x y = (\_ -> PwElement "ruby" x y)
+ruby x y _ = PwElement "ruby" x y
 
 ruby' :: Sig s opq
 ruby' = PwElement "ruby"
 
 ruby_ :: AFSig_ s opq
-ruby_ x = (\_ -> PwElement "ruby" dats x)
+ruby_ x _ = PwElement "ruby" dats x
 
 ruby'_ :: Sig_ s opq
-ruby'_ x = PwElement "ruby" dats x
+ruby'_ = PwElement "ruby" dats
 
 ruby__ :: AFSig__ s opq
-ruby__ x = (\_ -> PwElement "ruby" dats [txt x])
+ruby__ x _ = PwElement "ruby" dats [txt x]
 
 ruby'__ :: Sig__ s opq
 ruby'__ x = PwElement "ruby" dats [txt x]
 
 
 s :: AFSig s opq
-s x y = (\_ -> PwElement "s" x y)
+s x y _ = PwElement "s" x y
 
 s' :: Sig s opq
 s' = PwElement "s"
 
 s_ :: AFSig_ s opq
-s_ x = (\_ -> PwElement "s" dats x)
+s_ x _ = PwElement "s" dats x
 
 s'_ :: Sig_ s opq
-s'_ x = PwElement "s" dats x
+s'_ = PwElement "s" dats
 
 s__ :: AFSig__ s opq
-s__ x = (\_ -> PwElement "s" dats [txt x])
+s__ x _ = PwElement "s" dats [txt x]
 
 s'__ :: Sig__ s opq
 s'__ x = PwElement "s" dats [txt x]
 
 
 samp :: AFSig s opq
-samp x y = (\_ -> PwElement "samp" x y)
+samp x y _ = PwElement "samp" x y
 
 samp' :: Sig s opq
 samp' = PwElement "samp"
 
 samp_ :: AFSig_ s opq
-samp_ x = (\_ -> PwElement "samp" dats x)
+samp_ x _ = PwElement "samp" dats x
 
 samp'_ :: Sig_ s opq
-samp'_ x = PwElement "samp" dats x
+samp'_ = PwElement "samp" dats
 
 samp__ :: AFSig__ s opq
-samp__ x = (\_ -> PwElement "samp" dats [txt x])
+samp__ x _ = PwElement "samp" dats [txt x]
 
 samp'__ :: Sig__ s opq
 samp'__ x = PwElement "samp" dats [txt x]
 
 
 script :: AFSig s opq
-script x y = (\_ -> PwElement "script" x y)
+script x y _ = PwElement "script" x y
 
 script' :: Sig s opq
 script' = PwElement "script"
 
 script_ :: AFSig_ s opq
-script_ x = (\_ -> PwElement "script" dats x)
+script_ x _ = PwElement "script" dats x
 
 script'_ :: Sig_ s opq
-script'_ x = PwElement "script" dats x
+script'_ = PwElement "script" dats
 
 script__ :: AFSig__ s opq
-script__ x = (\_ -> PwElement "script" dats [txt x])
+script__ x _ = PwElement "script" dats [txt x]
 
 script'__ :: Sig__ s opq
 script'__ x = PwElement "script" dats [txt x]
 
 
 section :: AFSig s opq
-section x y = (\_ -> PwElement "section" x y)
+section x y _ = PwElement "section" x y
 
 section' :: Sig s opq
 section' = PwElement "section"
 
 section_ :: AFSig_ s opq
-section_ x = (\_ -> PwElement "section" dats x)
+section_ x _ = PwElement "section" dats x
 
 section'_ :: Sig_ s opq
-section'_ x = PwElement "section" dats x
+section'_ = PwElement "section" dats
 
 section__ :: AFSig__ s opq
-section__ x = (\_ -> PwElement "section" dats [txt x])
+section__ x _ = PwElement "section" dats [txt x]
 
 section'__ :: Sig__ s opq
 section'__ x = PwElement "section" dats [txt x]
 
 
 select :: AFSig s opq
-select x y = (\_ -> PwElement "select" x y)
+select x y _ = PwElement "select" x y
 
 select' :: Sig s opq
 select' = PwElement "select"
 
 select_ :: AFSig_ s opq
-select_ x = (\_ -> PwElement "select" dats x)
+select_ x _ = PwElement "select" dats x
 
 select'_ :: Sig_ s opq
-select'_ x = PwElement "select" dats x
+select'_ = PwElement "select" dats
 
 select__ :: AFSig__ s opq
-select__ x = (\_ -> PwElement "select" dats [txt x])
+select__ x _ = PwElement "select" dats [txt x]
 
 select'__ :: Sig__ s opq
 select'__ x = PwElement "select" dats [txt x]
 
 
 small :: AFSig s opq
-small x y = (\_ -> PwElement "small" x y)
+small x y _ = PwElement "small" x y
 
 small' :: Sig s opq
 small' = PwElement "small"
 
 small_ :: AFSig_ s opq
-small_ x = (\_ -> PwElement "small" dats x)
+small_ x _ = PwElement "small" dats x
 
 small'_ :: Sig_ s opq
-small'_ x = PwElement "small" dats x
+small'_ = PwElement "small" dats
 
 small__ :: AFSig__ s opq
-small__ x = (\_ -> PwElement "small" dats [txt x])
+small__ x _ = PwElement "small" dats [txt x]
 
 small'__ :: Sig__ s opq
 small'__ x = PwElement "small" dats [txt x]
 
 
 source :: AFSig s opq
-source x y = (\_ -> PwElement "source" x y)
+source x y _ = PwElement "source" x y
 
 source' :: Sig s opq
 source' = PwElement "source"
 
 source_ :: AFSig_ s opq
-source_ x = (\_ -> PwElement "source" dats x)
+source_ x _ = PwElement "source" dats x
 
 source'_ :: Sig_ s opq
-source'_ x = PwElement "source" dats x
+source'_ = PwElement "source" dats
 
 source__ :: AFSig__ s opq
-source__ x = (\_ -> PwElement "source" dats [txt x])
+source__ x _ = PwElement "source" dats [txt x]
 
 source'__ :: Sig__ s opq
 source'__ x = PwElement "source" dats [txt x]
 
 
 span :: AFSig s opq
-span x y = (\_ -> PwElement "span" x y)
+span x y _ = PwElement "span" x y
 
 span' :: Sig s opq
 span' = PwElement "span"
 
 span_ :: AFSig_ s opq
-span_ x = (\_ -> PwElement "span" dats x)
+span_ x _ = PwElement "span" dats x
 
 span'_ :: Sig_ s opq
-span'_ x = PwElement "span" dats x
+span'_ = PwElement "span" dats
 
 span__ :: AFSig__ s opq
-span__ x = (\_ -> PwElement "span" dats [txt x])
+span__ x _ = PwElement "span" dats [txt x]
 
 span'__ :: Sig__ s opq
 span'__ x = PwElement "span" dats [txt x]
 
 
 strike :: AFSig s opq
-strike x y = (\_ -> PwElement "strike" x y)
+strike x y _ = PwElement "strike" x y
 
 strike' :: Sig s opq
 strike' = PwElement "strike"
 
 strike_ :: AFSig_ s opq
-strike_ x = (\_ -> PwElement "strike" dats x)
+strike_ x _ = PwElement "strike" dats x
 
 strike'_ :: Sig_ s opq
-strike'_ x = PwElement "strike" dats x
+strike'_ = PwElement "strike" dats
 
 strike__ :: AFSig__ s opq
-strike__ x = (\_ -> PwElement "strike" dats [txt x])
+strike__ x _ = PwElement "strike" dats [txt x]
 
 strike'__ :: Sig__ s opq
 strike'__ x = PwElement "strike" dats [txt x]
 
 
 strong :: AFSig s opq
-strong x y = (\_ -> PwElement "strong" x y)
+strong x y _ = PwElement "strong" x y
 
 strong' :: Sig s opq
 strong' = PwElement "strong"
 
 strong_ :: AFSig_ s opq
-strong_ x = (\_ -> PwElement "strong" dats x)
+strong_ x _ = PwElement "strong" dats x
 
 strong'_ :: Sig_ s opq
-strong'_ x = PwElement "strong" dats x
+strong'_ = PwElement "strong" dats
 
 strong__ :: AFSig__ s opq
-strong__ x = (\_ -> PwElement "strong" dats [txt x])
+strong__ x _ = PwElement "strong" dats [txt x]
 
 strong'__ :: Sig__ s opq
 strong'__ x = PwElement "strong" dats [txt x]
 
 
 style :: AFSig s opq
-style x y = (\_ -> PwElement "style" x y)
+style x y _ = PwElement "style" x y
 
 style' :: Sig s opq
 style' = PwElement "style"
 
 style_ :: AFSig_ s opq
-style_ x = (\_ -> PwElement "style" dats x)
+style_ x _ = PwElement "style" dats x
 
 style'_ :: Sig_ s opq
-style'_ x = PwElement "style" dats x
+style'_ = PwElement "style" dats
 
 style__ :: AFSig__ s opq
-style__ x = (\_ -> PwElement "style" dats [txt x])
+style__ x _ = PwElement "style" dats [txt x]
 
 style'__ :: Sig__ s opq
 style'__ x = PwElement "style" dats [txt x]
 
 
 sub :: AFSig s opq
-sub x y = (\_ -> PwElement "sub" x y)
+sub x y _ = PwElement "sub" x y
 
 sub' :: Sig s opq
 sub' = PwElement "sub"
 
 sub_ :: AFSig_ s opq
-sub_ x = (\_ -> PwElement "sub" dats x)
+sub_ x _ = PwElement "sub" dats x
 
 sub'_ :: Sig_ s opq
-sub'_ x = PwElement "sub" dats x
+sub'_ = PwElement "sub" dats
 
 sub__ :: AFSig__ s opq
-sub__ x = (\_ -> PwElement "sub" dats [txt x])
+sub__ x _ = PwElement "sub" dats [txt x]
 
 sub'__ :: Sig__ s opq
 sub'__ x = PwElement "sub" dats [txt x]
 
 
 summary :: AFSig s opq
-summary x y = (\_ -> PwElement "summary" x y)
+summary x y _ = PwElement "summary" x y
 
 summary' :: Sig s opq
 summary' = PwElement "summary"
 
 summary_ :: AFSig_ s opq
-summary_ x = (\_ -> PwElement "summary" dats x)
+summary_ x _ = PwElement "summary" dats x
 
 summary'_ :: Sig_ s opq
-summary'_ x = PwElement "summary" dats x
+summary'_ = PwElement "summary" dats
 
 summary__ :: AFSig__ s opq
-summary__ x = (\_ -> PwElement "summary" dats [txt x])
+summary__ x _ = PwElement "summary" dats [txt x]
 
 summary'__ :: Sig__ s opq
 summary'__ x = PwElement "summary" dats [txt x]
 
 
 sup :: AFSig s opq
-sup x y = (\_ -> PwElement "sup" x y)
+sup x y _ = PwElement "sup" x y
 
 sup' :: Sig s opq
 sup' = PwElement "sup"
 
 sup_ :: AFSig_ s opq
-sup_ x = (\_ -> PwElement "sup" dats x)
+sup_ x _ = PwElement "sup" dats x
 
 sup'_ :: Sig_ s opq
-sup'_ x = PwElement "sup" dats x
+sup'_ = PwElement "sup" dats
 
 sup__ :: AFSig__ s opq
-sup__ x = (\_ -> PwElement "sup" dats [txt x])
+sup__ x _ = PwElement "sup" dats [txt x]
 
 sup'__ :: Sig__ s opq
 sup'__ x = PwElement "sup" dats [txt x]
 
 
 svg :: AFSig s opq
-svg x y = (\_ -> PwElement "svg" x y)
+svg x y _ = PwElement "svg" x y
 
 svg' :: Sig s opq
 svg' = PwElement "svg"
 
 svg_ :: AFSig_ s opq
-svg_ x = (\_ -> PwElement "svg" dats x)
+svg_ x _ = PwElement "svg" dats x
 
 svg'_ :: Sig_ s opq
-svg'_ x = PwElement "svg" dats x
+svg'_ = PwElement "svg" dats
 
 svg__ :: AFSig__ s opq
-svg__ x = (\_ -> PwElement "svg" dats [txt x])
+svg__ x _ = PwElement "svg" dats [txt x]
 
 svg'__ :: Sig__ s opq
 svg'__ x = PwElement "svg" dats [txt x]
 
 
 table :: AFSig s opq
-table x y = (\_ -> PwElement "table" x y)
+table x y _ = PwElement "table" x y
 
 table' :: Sig s opq
 table' = PwElement "table"
 
 table_ :: AFSig_ s opq
-table_ x = (\_ -> PwElement "table" dats x)
+table_ x _ = PwElement "table" dats x
 
 table'_ :: Sig_ s opq
-table'_ x = PwElement "table" dats x
+table'_ = PwElement "table" dats
 
 table__ :: AFSig__ s opq
-table__ x = (\_ -> PwElement "table" dats [txt x])
+table__ x _ = PwElement "table" dats [txt x]
 
 table'__ :: Sig__ s opq
 table'__ x = PwElement "table" dats [txt x]
 
 
 tbody :: AFSig s opq
-tbody x y = (\_ -> PwElement "tbody" x y)
+tbody x y _ = PwElement "tbody" x y
 
 tbody' :: Sig s opq
 tbody' = PwElement "tbody"
 
 tbody_ :: AFSig_ s opq
-tbody_ x = (\_ -> PwElement "tbody" dats x)
+tbody_ x _ = PwElement "tbody" dats x
 
 tbody'_ :: Sig_ s opq
-tbody'_ x = PwElement "tbody" dats x
+tbody'_ = PwElement "tbody" dats
 
 tbody__ :: AFSig__ s opq
-tbody__ x = (\_ -> PwElement "tbody" dats [txt x])
+tbody__ x _ = PwElement "tbody" dats [txt x]
 
 tbody'__ :: Sig__ s opq
 tbody'__ x = PwElement "tbody" dats [txt x]
 
 
 td :: AFSig s opq
-td x y = (\_ -> PwElement "td" x y)
+td x y _ = PwElement "td" x y
 
 td' :: Sig s opq
 td' = PwElement "td"
 
 td_ :: AFSig_ s opq
-td_ x = (\_ -> PwElement "td" dats x)
+td_ x _ = PwElement "td" dats x
 
 td'_ :: Sig_ s opq
-td'_ x = PwElement "td" dats x
+td'_ = PwElement "td" dats
 
 td__ :: AFSig__ s opq
-td__ x = (\_ -> PwElement "td" dats [txt x])
+td__ x _ = PwElement "td" dats [txt x]
 
 td'__ :: Sig__ s opq
 td'__ x = PwElement "td" dats [txt x]
 
 
 template :: AFSig s opq
-template x y = (\_ -> PwElement "template" x y)
+template x y _ = PwElement "template" x y
 
 template' :: Sig s opq
 template' = PwElement "template"
 
 template_ :: AFSig_ s opq
-template_ x = (\_ -> PwElement "template" dats x)
+template_ x _ = PwElement "template" dats x
 
 template'_ :: Sig_ s opq
-template'_ x = PwElement "template" dats x
+template'_ = PwElement "template" dats
 
 template__ :: AFSig__ s opq
-template__ x = (\_ -> PwElement "template" dats [txt x])
+template__ x _ = PwElement "template" dats [txt x]
 
 template'__ :: Sig__ s opq
 template'__ x = PwElement "template" dats [txt x]
 
 
 textarea :: AFSig s opq
-textarea x y = (\_ -> PwElement "textarea" x y)
+textarea x y _ = PwElement "textarea" x y
 
 textarea' :: Sig s opq
 textarea' = PwElement "textarea"
 
 textarea_ :: AFSig_ s opq
-textarea_ x = (\_ -> PwElement "textarea" dats x)
+textarea_ x _ = PwElement "textarea" dats x
 
 textarea'_ :: Sig_ s opq
-textarea'_ x = PwElement "textarea" dats x
+textarea'_ = PwElement "textarea" dats
 
 textarea__ :: AFSig__ s opq
-textarea__ x = (\_ -> PwElement "textarea" dats [txt x])
+textarea__ x _ = PwElement "textarea" dats [txt x]
 
 textarea'__ :: Sig__ s opq
 textarea'__ x = PwElement "textarea" dats [txt x]
 
 
 tfoot :: AFSig s opq
-tfoot x y = (\_ -> PwElement "tfoot" x y)
+tfoot x y _ = PwElement "tfoot" x y
 
 tfoot' :: Sig s opq
 tfoot' = PwElement "tfoot"
 
 tfoot_ :: AFSig_ s opq
-tfoot_ x = (\_ -> PwElement "tfoot" dats x)
+tfoot_ x _ = PwElement "tfoot" dats x
 
 tfoot'_ :: Sig_ s opq
-tfoot'_ x = PwElement "tfoot" dats x
+tfoot'_ = PwElement "tfoot" dats
 
 tfoot__ :: AFSig__ s opq
-tfoot__ x = (\_ -> PwElement "tfoot" dats [txt x])
+tfoot__ x _ = PwElement "tfoot" dats [txt x]
 
 tfoot'__ :: Sig__ s opq
 tfoot'__ x = PwElement "tfoot" dats [txt x]
 
 
 th :: AFSig s opq
-th x y = (\_ -> PwElement "th" x y)
+th x y _ = PwElement "th" x y
 
 th' :: Sig s opq
 th' = PwElement "th"
 
 th_ :: AFSig_ s opq
-th_ x = (\_ -> PwElement "th" dats x)
+th_ x _ = PwElement "th" dats x
 
 th'_ :: Sig_ s opq
-th'_ x = PwElement "th" dats x
+th'_ = PwElement "th" dats
 
 th__ :: AFSig__ s opq
-th__ x = (\_ -> PwElement "th" dats [txt x])
+th__ x _ = PwElement "th" dats [txt x]
 
 th'__ :: Sig__ s opq
 th'__ x = PwElement "th" dats [txt x]
 
 
 thead :: AFSig s opq
-thead x y = (\_ -> PwElement "thead" x y)
+thead x y _ = PwElement "thead" x y
 
 thead' :: Sig s opq
 thead' = PwElement "thead"
 
 thead_ :: AFSig_ s opq
-thead_ x = (\_ -> PwElement "thead" dats x)
+thead_ x _ = PwElement "thead" dats x
 
 thead'_ :: Sig_ s opq
-thead'_ x = PwElement "thead" dats x
+thead'_ = PwElement "thead" dats
 
 thead__ :: AFSig__ s opq
-thead__ x = (\_ -> PwElement "thead" dats [txt x])
+thead__ x _ = PwElement "thead" dats [txt x]
 
 thead'__ :: Sig__ s opq
 thead'__ x = PwElement "thead" dats [txt x]
 
 
 time :: AFSig s opq
-time x y = (\_ -> PwElement "time" x y)
+time x y _ = PwElement "time" x y
 
 time' :: Sig s opq
 time' = PwElement "time"
 
 time_ :: AFSig_ s opq
-time_ x = (\_ -> PwElement "time" dats x)
+time_ x _ = PwElement "time" dats x
 
 time'_ :: Sig_ s opq
-time'_ x = PwElement "time" dats x
+time'_ = PwElement "time" dats
 
 time__ :: AFSig__ s opq
-time__ x = (\_ -> PwElement "time" dats [txt x])
+time__ x _ = PwElement "time" dats [txt x]
 
 time'__ :: Sig__ s opq
 time'__ x = PwElement "time" dats [txt x]
 
 
 title :: AFSig s opq
-title x y = (\_ -> PwElement "title" x y)
+title x y _ = PwElement "title" x y
 
 title' :: Sig s opq
 title' = PwElement "title"
 
 title_ :: AFSig_ s opq
-title_ x = (\_ -> PwElement "title" dats x)
+title_ x _ = PwElement "title" dats x
 
 title'_ :: Sig_ s opq
-title'_ x = PwElement "title" dats x
+title'_ = PwElement "title" dats
 
 title__ :: AFSig__ s opq
-title__ x = (\_ -> PwElement "title" dats [txt x])
+title__ x _ = PwElement "title" dats [txt x]
 
 title'__ :: Sig__ s opq
 title'__ x = PwElement "title" dats [txt x]
 
 
 tr :: AFSig s opq
-tr x y = (\_ -> PwElement "tr" x y)
+tr x y _ = PwElement "tr" x y
 
 tr' :: Sig s opq
 tr' = PwElement "tr"
 
 tr_ :: AFSig_ s opq
-tr_ x = (\_ -> PwElement "tr" dats x)
+tr_ x _ = PwElement "tr" dats x
 
 tr'_ :: Sig_ s opq
-tr'_ x = PwElement "tr" dats x
+tr'_ = PwElement "tr" dats
 
 tr__ :: AFSig__ s opq
-tr__ x = (\_ -> PwElement "tr" dats [txt x])
+tr__ x _ = PwElement "tr" dats [txt x]
 
 tr'__ :: Sig__ s opq
 tr'__ x = PwElement "tr" dats [txt x]
 
 
 track :: AFSig s opq
-track x y = (\_ -> PwElement "track" x y)
+track x y _ = PwElement "track" x y
 
 track' :: Sig s opq
 track' = PwElement "track"
 
 track_ :: AFSig_ s opq
-track_ x = (\_ -> PwElement "track" dats x)
+track_ x _ = PwElement "track" dats x
 
 track'_ :: Sig_ s opq
-track'_ x = PwElement "track" dats x
+track'_ = PwElement "track" dats
 
 track__ :: AFSig__ s opq
-track__ x = (\_ -> PwElement "track" dats [txt x])
+track__ x _ = PwElement "track" dats [txt x]
 
 track'__ :: Sig__ s opq
 track'__ x = PwElement "track" dats [txt x]
 
 
 tt :: AFSig s opq
-tt x y = (\_ -> PwElement "tt" x y)
+tt x y _ = PwElement "tt" x y
 
 tt' :: Sig s opq
 tt' = PwElement "tt"
 
 tt_ :: AFSig_ s opq
-tt_ x = (\_ -> PwElement "tt" dats x)
+tt_ x _ = PwElement "tt" dats x
 
 tt'_ :: Sig_ s opq
-tt'_ x = PwElement "tt" dats x
+tt'_ = PwElement "tt" dats
 
 tt__ :: AFSig__ s opq
-tt__ x = (\_ -> PwElement "tt" dats [txt x])
+tt__ x _ = PwElement "tt" dats [txt x]
 
 tt'__ :: Sig__ s opq
 tt'__ x = PwElement "tt" dats [txt x]
 
 
 u :: AFSig s opq
-u x y = (\_ -> PwElement "u" x y)
+u x y _ = PwElement "u" x y
 
 u' :: Sig s opq
 u' = PwElement "u"
 
 u_ :: AFSig_ s opq
-u_ x = (\_ -> PwElement "u" dats x)
+u_ x _ = PwElement "u" dats x
 
 u'_ :: Sig_ s opq
-u'_ x = PwElement "u" dats x
+u'_ = PwElement "u" dats
 
 u__ :: AFSig__ s opq
-u__ x = (\_ -> PwElement "u" dats [txt x])
+u__ x _ = PwElement "u" dats [txt x]
 
 u'__ :: Sig__ s opq
 u'__ x = PwElement "u" dats [txt x]
 
 
 ul :: AFSig s opq
-ul x y = (\_ -> PwElement "ul" x y)
+ul x y _ = PwElement "ul" x y
 
 ul' :: Sig s opq
 ul' = PwElement "ul"
 
 ul_ :: AFSig_ s opq
-ul_ x = (\_ -> PwElement "ul" dats x)
+ul_ x _ = PwElement "ul" dats x
 
 ul'_ :: Sig_ s opq
-ul'_ x = PwElement "ul" dats x
+ul'_ = PwElement "ul" dats
 
 ul__ :: AFSig__ s opq
-ul__ x = (\_ -> PwElement "ul" dats [txt x])
+ul__ x _ = PwElement "ul" dats [txt x]
 
 ul'__ :: Sig__ s opq
 ul'__ x = PwElement "ul" dats [txt x]
 
 
 var :: AFSig s opq
-var x y = (\_ -> PwElement "var" x y)
+var x y _ = PwElement "var" x y
 
 var' :: Sig s opq
 var' = PwElement "var"
 
 var_ :: AFSig_ s opq
-var_ x = (\_ -> PwElement "var" dats x)
+var_ x _ = PwElement "var" dats x
 
 var'_ :: Sig_ s opq
-var'_ x = PwElement "var" dats x
+var'_ = PwElement "var" dats
 
 var__ :: AFSig__ s opq
-var__ x = (\_ -> PwElement "var" dats [txt x])
+var__ x _ = PwElement "var" dats [txt x]
 
 var'__ :: Sig__ s opq
 var'__ x = PwElement "var" dats [txt x]
 
 
 video :: AFSig s opq
-video x y = (\_ -> PwElement "video" x y)
+video x y _ = PwElement "video" x y
 
 video' :: Sig s opq
 video' = PwElement "video"
 
 video_ :: AFSig_ s opq
-video_ x = (\_ -> PwElement "video" dats x)
+video_ x _ = PwElement "video" dats x
 
 video'_ :: Sig_ s opq
-video'_ x = PwElement "video" dats x
+video'_ = PwElement "video" dats
 
 video__ :: AFSig__ s opq
-video__ x = (\_ -> PwElement "video" dats [txt x])
+video__ x _ = PwElement "video" dats [txt x]
 
 video'__ :: Sig__ s opq
 video'__ x = PwElement "video" dats [txt x]
 
 
 wbr :: (s -> PwNode s opq)
-wbr = (\_ -> PwElement "br" dats [])
+wbr _ = PwElement "br" dats []
 
 txt :: String -> (s -> PwNode s opq)
-txt t = (\_ -> PwTextNode t)
+txt t _ = PwTextNode t
 
 txt' :: String -> PwNode s opq
 txt' = PwTextNode
 
 
 h1 :: AFSig s opq
-h1 x y = (\_ -> PwElement "h1" x y)
+h1 x y _ = PwElement "h1" x y
 
 h1' :: Sig s opq
 h1' = PwElement "h1"
 
 h1_ :: AFSig_ s opq
-h1_ x = (\_ -> PwElement "h1" dats x)
+h1_ x _ = PwElement "h1" dats x
 
 h1'_ :: Sig_ s opq
-h1'_ x = PwElement "h1" dats x
+h1'_ = PwElement "h1" dats
 
 h1__ :: AFSig__ s opq
-h1__ x = (\_ -> PwElement "h1" dats [txt x])
+h1__ x _ = PwElement "h1" dats [txt x]
 
 h1'__ :: Sig__ s opq
 h1'__ x = PwElement "h1" dats [txt x]
 
 
 h2 :: AFSig s opq
-h2 x y = (\_ -> PwElement "h2" x y)
+h2 x y _ = PwElement "h2" x y
 
 h2' :: Sig s opq
 h2' = PwElement "h2"
 
 h2_ :: AFSig_ s opq
-h2_ x = (\_ -> PwElement "h2" dats x)
+h2_ x _ = PwElement "h2" dats x
 
 h2'_ :: Sig_ s opq
-h2'_ x = PwElement "h2" dats x
+h2'_ = PwElement "h2" dats
 
 h2__ :: AFSig__ s opq
-h2__ x = (\_ -> PwElement "h2" dats [txt x])
+h2__ x _ = PwElement "h2" dats [txt x]
 
 h2'__ :: Sig__ s opq
 h2'__ x = PwElement "h2" dats [txt x]
 
 
 h3 :: AFSig s opq
-h3 x y = (\_ -> PwElement "h3" x y)
+h3 x y _ = PwElement "h3" x y
 
 h3' :: Sig s opq
 h3' = PwElement "h3"
 
 h3_ :: AFSig_ s opq
-h3_ x = (\_ -> PwElement "h3" dats x)
+h3_ x _ = PwElement "h3" dats x
 
 h3'_ :: Sig_ s opq
-h3'_ x = PwElement "h3" dats x
+h3'_ = PwElement "h3" dats
 
 h3__ :: AFSig__ s opq
-h3__ x = (\_ -> PwElement "h3" dats [txt x])
+h3__ x _ = PwElement "h3" dats [txt x]
 
 h3'__ :: Sig__ s opq
 h3'__ x = PwElement "h3" dats [txt x]
 
 
 h4 :: AFSig s opq
-h4 x y = (\_ -> PwElement "h4" x y)
+h4 x y _ = PwElement "h4" x y
 
 h4' :: Sig s opq
 h4' = PwElement "h4"
 
 h4_ :: AFSig_ s opq
-h4_ x = (\_ -> PwElement "h4" dats x)
+h4_ x _ = PwElement "h4" dats x
 
 h4'_ :: Sig_ s opq
-h4'_ x = PwElement "h4" dats x
+h4'_ = PwElement "h4" dats
 
 h4__ :: AFSig__ s opq
-h4__ x = (\_ -> PwElement "h4" dats [txt x])
+h4__ x _ = PwElement "h4" dats [txt x]
 
 h4'__ :: Sig__ s opq
 h4'__ x = PwElement "h4" dats [txt x]
 
 
 h5 :: AFSig s opq
-h5 x y = (\_ -> PwElement "h5" x y)
+h5 x y _ = PwElement "h5" x y
 
 h5' :: Sig s opq
 h5' = PwElement "h5"
 
 h5_ :: AFSig_ s opq
-h5_ x = (\_ -> PwElement "h5" dats x)
+h5_ x _ = PwElement "h5" dats x
 
 h5'_ :: Sig_ s opq
-h5'_ x = PwElement "h5" dats x
+h5'_ = PwElement "h5" dats
 
 h5__ :: AFSig__ s opq
-h5__ x = (\_ -> PwElement "h5" dats [txt x])
+h5__ x _ = PwElement "h5" dats [txt x]
 
 h5'__ :: Sig__ s opq
 h5'__ x = PwElement "h5" dats [txt x]
 
 
 h6 :: AFSig s opq
-h6 x y = (\_ -> PwElement "h6" x y)
+h6 x y _ = PwElement "h6" x y
 
 h6' :: Sig s opq
 h6' = PwElement "h6"
 
 h6_ :: AFSig_ s opq
-h6_ x = (\_ -> PwElement "h6" dats x)
+h6_ x _ = PwElement "h6" dats x
 
 h6'_ :: Sig_ s opq
-h6'_ x = PwElement "h6" dats x
+h6'_ = PwElement "h6" dats
 
 h6__ :: AFSig__ s opq
-h6__ x = (\_ -> PwElement "h6" dats [txt x])
+h6__ x _ = PwElement "h6" dats [txt x]
 
 h6'__ :: Sig__ s opq
 h6'__ x = PwElement "h6" dats [txt x]
src/Web/Framework/Plzwrk/Util.hs view
@@ -29,177 +29,176 @@                                                 , dats'
                                                 , PwAttribute(..)
                                                 )
-import           Web.Framework.Plzwrk.Browserful
+import           Web.Framework.Plzwrk.JSEnv
 
 -- | Creates a text attribute wrapped in an applicative functor
-pT :: String -> (s -> PwAttribute s opq)
-pT t = (\_ -> PwTextAttribute t)
+pT :: String -> s -> PwAttribute s opq
+pT t _ = PwTextAttribute t
 
 -- | Creates a callback attribute wrapped in an applicative functor
-pF :: (opq -> s -> IO s) -> (s -> PwAttribute s opq)
-pF f = (\_ -> PwFunctionAttribute f)
+pF :: (opq -> s -> IO s) -> s -> PwAttribute s opq
+pF f _ = PwFunctionAttribute f
 
 -- |From an event, gets the target's value.
 eventTargetValue
-  :: Browserful jsval -- ^ the browser
+  :: JSEnv jsval -- ^ the browser
   -> jsval -- ^ the event
   -> IO (Maybe String) -- ^ the target value, or nothing if it doesn't exist
 eventTargetValue browser e = do
-  opq <- (getPropertyAsOpaque browser) e "target"
-  maybe (pure Nothing) (\y -> (getPropertyAsString browser) y "value") opq
+  opq <- getPropertyAsOpaque browser e "target"
+  maybe (pure Nothing) (\y -> getPropertyAsString browser y "value") opq
 
 -- |From an event, takes the target and blurs it.
 eventTargetBlur
-  :: Browserful jsval -- ^ the browser
+  :: JSEnv jsval -- ^ the browser
   -> jsval  -- ^ the event
   -> IO () -- ^ returns nothing
 eventTargetBlur browser e = do
-  opq <- (getPropertyAsOpaque browser) e "target"
-  maybe (pure ()) (\y -> void $ (invokeOn0 browser) y "blur") opq
+  opq <- getPropertyAsOpaque browser e "target"
+  maybe (pure ()) (\y -> void $ invokeOn0 browser y "blur") opq
 
 -- |Take an event and prevent the default.
 eventPreventDefault
-  :: Browserful jsval -- ^ the browser
+  :: JSEnv jsval -- ^ the browser
   -> jsval -- ^ the event
   -> IO () -- ^ returns nothing
-eventPreventDefault browser e = do
-  void $ (invokeOn0 browser) e "preventDefault"
+eventPreventDefault browser e = void $ invokeOn0 browser e "preventDefault"
 
 -----------
 
 -- | Sets on an element an attribute. See [Element.setAttribute](https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute)
 elementSetAttribute
-  :: Browserful jsval -- ^ The browser
+  :: JSEnv jsval -- ^ The browser
   -> jsval -- ^ the node
   -> String -- ^ the attribute name
   -> String -- ^ the attribute
   -> IO () -- ^ returns nothing
 elementSetAttribute b e k v = do
-  _k <- (jsValFromString b) k
-  _v <- (jsValFromString b) v
-  void $ (invokeOn2 b) e "setAttribute" _k _v
+  _k <- jsValFromString b k
+  _v <- jsValFromString b v
+  void $ invokeOn2 b e "setAttribute" _k _v
 
 -- | Gets the tag name of an element.  See [Element.tagName](https://developer.mozilla.org/en-US/docs/Web/API/Element/tagName)
 elementTagName
-  :: Browserful jsval -- ^ the browser
+  :: JSEnv jsval -- ^ the browser
   -> jsval -- ^ the element
   -> IO (Maybe String) -- ^ Returns the tag name
 elementTagName b v = do
-  _o <- (getPropertyAsOpaque b) v "tagName"
-  maybe (pure Nothing) (\x -> (castToString b) x) _o
+  _o <- getPropertyAsOpaque b v "tagName"
+  maybe (pure Nothing) (castToString b) _o
 
 -- | Takes a target and an event name and adds a listener. See [EventTarget.addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
 eventTargetAddEventListener
-  :: Browserful jsval -- ^ the browser
+  :: JSEnv jsval -- ^ the browser
   -> jsval -- ^ the element
   -> String -- ^ the listener name. note that this should be "click" or "input", not "onclick" nor "oninput"
   -> jsval -- ^ the listener
   -> IO () -- ^ returns nothing
 eventTargetAddEventListener b e k v = do
-  _k <- (jsValFromString b) k
-  void $ (invokeOn2 b) e "addEventListener" _k v
+  _k <- jsValFromString b k
+  void $ invokeOn2 b e "addEventListener" _k v
 
 -- | Takes a target and an event name and removes a listener. See [EventTarget.removeEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener)
 eventTargetRemoveEventListener
-  :: Browserful jsval -- ^ the browser
+  :: JSEnv jsval -- ^ the browser
   -> jsval -- ^ the element
   -> String -- ^ the listener name. note that this should be "click" or "input", not "onclick" nor "oninput"
   -> jsval -- ^ the listener
   -> IO () -- ^ returns nothing
 eventTargetRemoveEventListener b e k v = do
-  _k <- (jsValFromString b) k
-  void $ (invokeOn2 b) e "removeEventListener" _k v
+  _k <- jsValFromString b k
+  void $ invokeOn2 b e "removeEventListener" _k v
 
 -- | Gets a JavaScript property as a bool, returning @Nothing@ if the object being called is null or undefined or the property cannot be cast to a bool.
 getPropertyAsBool
-  :: Browserful jsval -- ^ the browser
+  :: JSEnv jsval -- ^ the browser
   -> jsval -- ^ the object containing the property
   -> String -- ^ the property name
   -> IO (Maybe Bool) -- ^ the response if the property is a bool, else Nothing
 getPropertyAsBool b o k = do
-  _v <- (getPropertyAsOpaque b) o k
-  maybe (pure Nothing) (\x -> (castToBool b) x) _v
+  _v <- getPropertyAsOpaque b o k
+  maybe (pure Nothing) (castToBool b) _v
 
 -- | Gets a JavaScript property as a double, returning @Nothing@ if the object being called is null or undefined or the property cannot be cast to a double.
 getPropertyAsDouble
-  :: Browserful jsval -- ^ the browser
+  :: JSEnv jsval -- ^ the browser
   -> jsval -- ^ the object containing the property
   -> String -- ^ the property name
   -> IO (Maybe Double) -- ^ the response if the property is a double, else Nothing
 getPropertyAsDouble b o k = do
-  _v <- (getPropertyAsOpaque b) o k
-  maybe (pure Nothing) (\x -> (castToDouble b) x) _v
+  _v <- getPropertyAsOpaque b o k
+  maybe (pure Nothing) (castToDouble b) _v
 
 -- | Gets a JavaScript property as an int, returning @Nothing@ if the object being called is null or undefined or the property cannot be cast to an int.
 getPropertyAsInt
-  :: Browserful jsval -- ^ the browser
+  :: JSEnv jsval -- ^ the browser
   -> jsval -- ^ the object containing the property
   -> String -- ^ the property name
   -> IO (Maybe Int) -- ^ the response if the property is an int, else Nothing
 getPropertyAsInt b o k = do
-  _v <- (getPropertyAsOpaque b) o k
-  maybe (pure Nothing) (\x -> (castToInt b) x) _v
+  _v <- getPropertyAsOpaque b o k
+  maybe (pure Nothing) (castToInt b) _v
 
 -- | Gets a JavaScript property as an string, returning @Nothing@ if the object being called is null or undefined.
 getPropertyAsString
-  :: Browserful jsval -- ^ the browser
+  :: JSEnv jsval -- ^ the browser
   -> jsval -- ^ the object containing the property
   -> String -- ^ the property name
   -> IO (Maybe String) -- ^ the response
 getPropertyAsString b o k = do
-  _v <- (getPropertyAsOpaque b) o k
-  maybe (pure Nothing) (\x -> (castToString b) x) _v
+  _v <- getPropertyAsOpaque b o k
+  maybe (pure Nothing) (castToString b) _v
 
 -- | Takes an element and clicks it. Useful for testing. See [HTMLElement.click](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click)
-htmlElemenetClick :: Browserful jsval -> jsval -> IO ()
-htmlElemenetClick b e = void $ (invokeOn0 b) e "click"
+htmlElemenetClick :: JSEnv jsval -> jsval -> IO ()
+htmlElemenetClick b e = void $ invokeOn0 b e "click"
 
 -- | Logs a string. See [Console.log](https://developer.mozilla.org/en-US/docs/Web/API/Console/log)
-consoleLogS :: Browserful jsval -> String -> IO ()
+consoleLogS :: JSEnv jsval -> String -> IO ()
 consoleLogS b s = do
-  _s <- (jsValFromString b) s
-  (consoleLog b) _s
+  _s <- jsValFromString b s
+  consoleLog b _s
 
 -- | Takes a node and appends a child. See [Node.appendChild](https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild)
 nodeAppendChild
-  :: Browserful jsval -- ^ the browser
+  :: JSEnv jsval -- ^ the browser
   -> jsval -- ^ the node
   -> jsval -- ^ the child to append
   -> IO () -- ^ returns nothing
-nodeAppendChild b e v = void $ (invokeOn1 b) e "appendChild" v
+nodeAppendChild b e v = void $ invokeOn1 b e "appendChild" v
 
 -- | Get the children of a node. See [Node.childNodes](https://developer.mozilla.org/en-US/docs/Web/API/Node/childNodes)
 nodeChildNodes
-  :: Browserful jsval -- ^ the browser
+  :: JSEnv jsval -- ^ the browser
   -> jsval -- ^ the node
   -> IO (Maybe [jsval])
 nodeChildNodes b v = do
-  _cn <- (getPropertyAsOpaque b) v "childNodes"
-  maybe (pure Nothing) (\x -> (castToArray b) x) _cn
+  _cn <- getPropertyAsOpaque b v "childNodes"
+  maybe (pure Nothing) (castToArray b) _cn
 
 -- | Inserts a node into an element before another node.  See [Node.insertBefore](https://developer.mozilla.org/en-US/docs/Web/API/Node/insertBefore)
 nodeInsertBefore
-  :: Browserful jsval -- ^ the browser
+  :: JSEnv jsval -- ^ the browser
   -> jsval -- ^ the parent element
   -> jsval -- ^ the new node
   -> jsval -- ^ the pre-existing node
   -> IO () -- ^ returns nothing
-nodeInsertBefore b e k v = void $ (invokeOn2 b) e "insertBefore" k v
+nodeInsertBefore b e k v = void $ invokeOn2 b e "insertBefore" k v
 
 -- | Removes a child from a parent node.  See [Node.removeChild](https://developer.mozilla.org/en-US/docs/Web/API/Node/removeChild)
 nodeRemoveChild
-  :: Browserful jsval -- ^ the browser
+  :: JSEnv jsval -- ^ the browser
   -> jsval -- ^ the parent element
   -> jsval -- ^ the child to remove
   -> IO () -- ^ returns nothing
-nodeRemoveChild b e v = void $ (invokeOn1 b) e "removeChild" v
+nodeRemoveChild b e v = void $ invokeOn1 b e "removeChild" v
 
 -- | Gets the text content of a node. See [Node.textContent](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent)
 nodeTextContent
-  :: Browserful jsval -- ^ the browser
+  :: JSEnv jsval -- ^ the browser
   -> jsval -- ^ the node
   -> IO (Maybe String) -- ^ the text content as a string
 nodeTextContent b e = do
-  _tc <- (getPropertyAsOpaque b) e "textContent"
-  maybe (pure Nothing) (\x -> (castToString b) x) _tc
+  _tc <- getPropertyAsOpaque b e "textContent"
+  maybe (pure Nothing) (castToString b) _tc
 
test/DOMSpec.hs view
@@ -15,19 +15,19 @@                                                 , div'_
                                                 )
 
-nodeChildNodesOrThrow :: Browserful jsval -> jsval -> IO [jsval]
+nodeChildNodesOrThrow :: JSEnv jsval -> jsval -> IO [jsval]
 nodeChildNodesOrThrow b v = do
-  _v <- (nodeChildNodes b v)
+  _v <- nodeChildNodes b v
   maybe (error "Could not find child nodes") pure _v
 
-nodeTextContentOrThrow :: Browserful jsval -> jsval -> IO String
+nodeTextContentOrThrow :: JSEnv jsval -> jsval -> IO String
 nodeTextContentOrThrow b v = do
-  _v <- (nodeTextContent b v)
+  _v <- nodeTextContent b v
   maybe (error "Could not find text content") pure _v
 
-elementTagNameOrThrow :: Browserful jsval -> jsval -> IO String
+elementTagNameOrThrow :: JSEnv jsval -> jsval -> IO String
 elementTagNameOrThrow b v = do
-  _v <- (elementTagName b v)
+  _v <- elementTagName b v
   maybe (error "Could not find tag name") pure _v
 
 data MyState = MyState
@@ -39,7 +39,7 @@     let domF =
           (\x y -> div'_
               [ p [("style", pT "position:absolute")]
-                  (take y $ repeat (txt (concat [x, show y])))
+                  (replicate y (txt (x ++ show y)))
               , button
                 [("id", pT "incr"), ("class", pT "a b ccc"), ("click",
                   pF (\_ s -> pure $ s { _ctr = y + 1 })
@@ -60,51 +60,51 @@       mock <- makeMockBrowserWithContext rf
       plzwrk' domF state mock
       parentNode     <- documentBody mock
-      childrenLevel0 <- (nodeChildNodesOrThrow mock) parentNode
+      childrenLevel0 <- nodeChildNodesOrThrow mock parentNode
       length childrenLevel0 `shouldBe` 1
-      divtag <- (elementTagNameOrThrow mock) (head childrenLevel0)
+      divtag <- elementTagNameOrThrow mock (head childrenLevel0)
       divtag `shouldBe` "div"
-      childrenLevel1 <- (nodeChildNodesOrThrow mock) (head childrenLevel0)
+      childrenLevel1 <- nodeChildNodesOrThrow mock (head childrenLevel0)
       length childrenLevel1 `shouldBe` 4
-      ptag <- (elementTagNameOrThrow mock) (head childrenLevel1)
+      ptag <- elementTagNameOrThrow mock (head childrenLevel1)
       ptag `shouldBe` "p"
-      childrenLevel2 <- (nodeChildNodesOrThrow mock) (head childrenLevel1)
+      childrenLevel2 <- nodeChildNodesOrThrow mock (head childrenLevel1)
       length childrenLevel2 `shouldBe` 1
 
       -- increment 4 times
 
-      (documentGetElementById mock) "incr"
+      documentGetElementById mock "incr"
         >>= maybe (error "Incr node does not exist") (htmlElemenetClick mock)
-      (documentGetElementById mock) "incr"
+      documentGetElementById mock "incr"
         >>= maybe (error "Incr node does not exist") (htmlElemenetClick mock)
-      (documentGetElementById mock) "incr"
+      documentGetElementById mock "incr"
         >>= maybe (error "Incr node does not exist") (htmlElemenetClick mock)
-      (documentGetElementById mock) "incr"
+      documentGetElementById mock "incr"
         >>= maybe (error "Incr node does not exist") (htmlElemenetClick mock)
       parentNode'     <- documentBody mock
-      childrenLevel0' <- (nodeChildNodesOrThrow mock) parentNode'
+      childrenLevel0' <- nodeChildNodesOrThrow mock parentNode'
       length childrenLevel0' `shouldBe` 1
-      divtag' <- (elementTagNameOrThrow mock) (head childrenLevel0')
+      divtag' <- elementTagNameOrThrow mock (head childrenLevel0')
       divtag' `shouldBe` "div"
-      childrenLevel1' <- (nodeChildNodesOrThrow mock) (head childrenLevel0')
+      childrenLevel1' <- nodeChildNodesOrThrow mock (head childrenLevel0')
       length childrenLevel1' `shouldBe` 4
-      childrenLevel2' <- (nodeChildNodesOrThrow mock) (head childrenLevel1')
+      childrenLevel2' <- nodeChildNodesOrThrow mock (head childrenLevel1')
       length childrenLevel2' `shouldBe` 5
       content' <- mapM (nodeTextContentOrThrow mock) childrenLevel2'
-      content' `shouldBe` (take 5 $ repeat "Mike5")
-      (documentGetElementById mock) "decr"
+      content' `shouldBe` replicate 5 "Mike5"
+      documentGetElementById mock "decr"
         >>= maybe (error "Incr node does not exist") (htmlElemenetClick mock)
-      (documentGetElementById mock) "decr"
+      documentGetElementById mock "decr"
         >>= maybe (error "Incr node does not exist") (htmlElemenetClick mock)
       parentNode''     <- documentBody mock
-      childrenLevel0'' <- (nodeChildNodesOrThrow mock) parentNode''
+      childrenLevel0'' <- nodeChildNodesOrThrow mock parentNode''
       length childrenLevel0'' `shouldBe` 1
-      divtag'' <- (elementTagNameOrThrow mock) (head childrenLevel0'')
+      divtag'' <- elementTagNameOrThrow mock (head childrenLevel0'')
       divtag'' `shouldBe` "div"
-      childrenLevel1'' <- (nodeChildNodesOrThrow mock) (head childrenLevel0'')
+      childrenLevel1'' <- nodeChildNodesOrThrow mock (head childrenLevel0'')
       length childrenLevel1'' `shouldBe` 4
-      childrenLevel2'' <- (nodeChildNodesOrThrow mock) (head childrenLevel1'')
+      childrenLevel2'' <- nodeChildNodesOrThrow mock (head childrenLevel1'')
       length childrenLevel2'' `shouldBe` 3
       content'' <- mapM (nodeTextContentOrThrow mock) childrenLevel2''
-      content'' `shouldBe` (take 3 $ repeat "Mike3")
+      content'' `shouldBe` replicate 3 "Mike3"
       toHTML domF state `shouldBe` "<div><p style=\"position:absolute\">Mike1</p><button id=\"incr\" class=\"a b ccc\">Increase counter</button><br/><button id=\"decr\" style=\"position:absolute;margin:10px\">Decrease counter</button></div>"
test/HSXSpec.hs view
@@ -18,7 +18,7 @@     -- we use () for an empty state
 
     _elt_tag (dom ()) `shouldBe` "p"
-    _tn_text (((_elt_children (dom ())) !! 0) ()) `shouldBe` "Hello world!"
+    _tn_text (head (_elt_children (dom ())) ()) `shouldBe` "Hello world!"
   it "Parses hsx with an event listener" $ do
     let dom = [hsx|
             <h1 id="foo" style="position:absolute">
@@ -42,8 +42,8 @@             </h1>
         |]
     _elt_tag (dom 3) `shouldBe` "h1"
-    _elt_tag (((_elt_children (dom 5)) !! 0) 3) `shouldBe` "a"
-    _tn_text (((_elt_children (dom 5)) !! 1) 3) `shouldBe` "hello world"
+    _elt_tag (head (_elt_children (dom 5)) 3) `shouldBe` "a"
+    _tn_text ((_elt_children (dom 5) !! 1) 3) `shouldBe` "hello world"
     1 `shouldBe` 1
   it "Parses hsx with a list of elements" $ do
     let mylink = [hsx|<a click=#c{(\_ x -> return $ x + 41)}#>Hello</a>|]
@@ -54,9 +54,9 @@             </h1>
         |]
     _elt_tag (dom 3) `shouldBe` "h1"
-    _elt_tag (((_elt_children (dom 5)) !! 0) 3) `shouldBe` "a"
-    _elt_tag (((_elt_children (dom 5)) !! 6) 3) `shouldBe` "a"
-    _tn_text (((_elt_children (dom 5)) !! 10) 3) `shouldBe` "hello world"
+    _elt_tag (head (_elt_children (dom 5)) 3) `shouldBe` "a"
+    _elt_tag ((_elt_children (dom 5) !! 6) 3) `shouldBe` "a"
+    _tn_text ((_elt_children (dom 5) !! 10) 3) `shouldBe` "hello world"
   it "Parses hsx mixing text and not text" $ do
     let mylink = [hsx|<a click=#c{(\_ x -> return $ x + 41)}#>Hello</a>|]
     let dom = [hsx|
@@ -65,8 +65,8 @@             </h1>
         |]
     _elt_tag (dom 3) `shouldBe` "h1"
-    _elt_tag (((_elt_children (dom 5)) !! 0) 3) `shouldBe` "div"
-    _elt_tag ((_elt_children (((_elt_children (dom 5)) !! 0) 3) !! 1) 5) `shouldBe` "span"
+    _elt_tag (head (_elt_children (dom 5)) 3) `shouldBe` "div"
+    _elt_tag ((_elt_children (head (_elt_children (dom 5)) 3) !! 1) 5) `shouldBe` "span"
   it "Parses hsx'" $ do
     let mylink = [hsx|<a click=#c{(\_ x -> return $ x + 41)}#>Hello</a>|]
     let dom = (\st -> [hsx'|
@@ -75,4 +75,4 @@             </h1>
         |])
     _elt_tag (dom 3) `shouldBe` "h1"
-    _elt_tag (((_elt_children (dom 5)) !! 0) 3) `shouldBe` "a"
+    _elt_tag (head (_elt_children (dom 5)) 3) `shouldBe` "a"