packages feed

plzwrk (empty) → 0.0.0.0

raw patch · 16 files changed

+5493/−0 lines, 16 filesdep +aesondep +asterius-preludedep +basesetup-changed

Dependencies added: aeson, asterius-prelude, base, bytestring, containers, hspec, mtl, neat-interpolation, plzwrk, random, text, transformers, unordered-containers

Files

+ ChangeLog.md view
@@ -0,0 +1,5 @@+# Changelog for plzwrk++## 0.0.0.0++- Initial release.
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Author name here (c) 2020++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Author name here nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,110 @@+# plzwrk
+
+A Haskell front-end framework.
+
+## Hello world
+
+```haskell
+import           Web.Framework.Plzwrk
+import           Web.Framework.Plzwrk.Asterius
+import           Web.Framework.Plzwrk.Tag (p__)
+
+main :: IO ()
+main = do
+  browser <- asteriusBrowser
+  plzwrk'_ (p__ "Hello world!") browser
+```
+
+See it [live](https://plzwrk-hello-world.surge.sh).
+
+## Kitchen sink
+
+Check out the code [here](./kitchen-sink/Main.hs).
+
+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 `-f plzwrk-enable-asterius` when running `ahc-cabal`.
+
+A minimal flow is shown below, mostly copied from the asterius documentation. It assumes that you have a cabal-buildable project in the root directory. Note the use of the `-f plzwrk-enable-asterius` flag in the `ahc-cabal` step.
+
+```bash
+username@hostname:~/my-dir$ docker run --rm -it -v $(pwd):/project -w /project terrorjack/asterius
+asterius@hostname:/project$ ahc-cabal new-install -f plzwrk-enable-asterius --installdir <inst-dir> <exec-name>
+asterius@hostname:/project$ cd <inst-dir> && ahc-dist --input-exe <exec-name> --browser --bundle
+```
+
+## Documentation
+
+The main documentation for `plzwrk` is on [hackage](https://https://hackage.haskell.org/package/plzwrk). The four importable modules are:
+
+- `Web.Frameworks.Plzwrk` for the basic functions
+- `Web.Frameworks.Plzwrk.Tag` for helper functions to make takes like `input` or `br`.
+- `Web.Frameworks.Plzwrk.MockJSVal` to use a mock browser.
+- `Web.Frameworks.Plzwrk.Asterius` to use a bindings for a real browser courtesy of [Asterius](https://github.com/tweag/asterius).
+
+## Design
+
+`plzwrk` is inspired by [redux](https://redux.js.org/) for its state management. The main idea is that you have a HTML-creation function that accepts one or more variables from a state that is composed, via applicative functors, with getters from a state.
+
+```haskell
+
+-- State
+data MyState = MkMyState { _name :: Text, age :: Int, _tags :: [Text] }
+
+-- Function hydrating a DOM with elementse from the state
+makeP = (\name age -> p'__ concat [name, " is the name and ", show age, " is my age."]) <$> _name <*> _age
+```
+
+HTML-creation functions can be nested, allowing for powerful abstractions.
+
+```haskell
+nested = div_ (take 10 $ repeat makeP)
+```
+
+HTML-creation functions use an apostrophe after the tag name (ie `div'`) if they accept arguments and no apostrophe (ie `div`) if they don't. Additionally, tags that do not have any attributes (class, style etc) are marked with a trailing underscore (`div_ [p__ "hello"]`), and tags that only accept text are marked with two trailing underscores (`p__ "hello"`).
+
+The HTML-creation function itself should be pure with type `(s -> Node s opq)`, where `s` is the type of the state and `opq` is the type of the opaque pointer used to represent a JavaScript value.  `opq` will rarely need to be provided manually as it is induced from the compiler based on the `Browserful` being used (ie `asteriusBrowser`).
+
+Event handlers take two arguments - an opaque pointer to the event and the current state - and return a new state (which could just be the original state) in the `IO` monad. For example, if the state is an integer, a valid event handler could be:
+
+```
+eh :: opq -> Int -> IO Int
+eh _ i = pure $ i + 1
+```
+
+To handle events (ie extract values from input events, etc) you can use one of the functions exported by `Web.Framework.Plzwrk`. Please see the [hackage documentation](https://hackage.haskell.org/package/plzwrk) for more information.
+
+> If you are using the Asterius backend, callback functions are still quite fragile and subject to breakage. The less third-party libraries you use in them, the better. For example, avoid using `Data.Text` and `aeson` if possible.
+
+## Testing your code
+
+Plzwrk comes with a mock browser that can act as a drop-in replacement for your browser. Use this in your tests.
+
+```haskell
+import Web.Framework.Plzwrk.MockJSVal
+
+main :: IO ()
+    browser <- makeMockBrowser
+    print "Now I'm using the mock browser."
+```
+
+## Using
+
+Plzwrk should be considered experimental. It is unfit for production and the syntax will change frequently, often in non-backward-compatible ways. There is a [changelog](ChangeLog.md).
+
+## Contributing
+
+Thanks for your interest in contributing! Here is a small list  of things I'd really appreciate help with:
+
+- Static site rendering
+- Automatic code splitting
+- Hot reloading
+- Documentation
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ hello-world/Main.hs view
@@ -0,0 +1,17 @@+{-# LANGUAGE CPP               #-}
+
+import           Web.Framework.Plzwrk
+#if defined(PLZWRK_ENABLE_ASTERIUS)
+import           Web.Framework.Plzwrk.Asterius
+import           Web.Framework.Plzwrk.Tag (p__)
+
+main :: IO ()
+main = do
+  browser <- asteriusBrowser
+  plzwrk'_ (p__ "Hello world!") browser
+
+
+# else
+main :: IO ()
+main = print "If you're using ahc, please set -DPLZWRK_ENABLE_ASTERIUS as a flag to run this executable."
+# endif
+ kitchen-sink/Main.hs view
@@ -0,0 +1,363 @@+{-# LANGUAGE CPP               #-}
+{-# LANGUAGE OverloadedStrings #-}
+#if defined(PLZWRK_ENABLE_ASTERIUS)
+{-# LANGUAGE QuasiQuotes #-}
+
+
+import           Asterius.Types
+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.Asterius
+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
+
+main :: IO ()
+main = do
+  browser <- asteriusBrowser
+  -- add some css!
+  _head   <- (getHead browser)
+  _style  <- (createElement browser) "style"
+  _css    <- (createTextNode browser) (DT.unpack myCss)
+  (appendChild browser) _style _css
+  (appendChild browser) _head _style
+  -- here is our "surprise" aphorism
+  let surpriseF =
+        (\noun -> if (length noun == 0)
+            then div'_ []
+            else p'__ $ concat ["Life is like", a_n noun, noun]
+          )
+          <$> _myNoun
+  -- here is our input
+  let
+    inputF = input
+      (pure dats'
+        { _simple   = singleton "type" "text"
+        , _style    = singleton "box-sizing" "content-box"
+        , _handlers = singleton
+                        "input"
+                        (\e s -> do
+                          opq <- (getOpaque browser) e "target"
+                          v   <- maybe (pure Nothing)
+                                       (\y -> (getString browser) y "value")
+                                       opq
+                          return $ maybe s (\q -> s { _myNoun = q }) v
+                        )
+        }
+      )
+      []
+  -- and here is our main div
+  let
+    mainDivF =
+      (\abstractToConcrete name -> T.main'_
+          [ section
+              (pure dats' { _class = S.singleton "content" })
+              [ h1__ "Aphorism Machine"
+              , ul
+                (pure dats' { _class = S.singleton "res" })
+                (fmap
+                  (\(abs, conc) ->
+                    (li__ (concat [abs, " is like", a_n conc, conc]))
+                  )
+                  abstractToConcrete
+                )
+              , br
+              , surpriseF
+              , div
+                (pure dats'
+                  { _style = fromList
+                               [("width", "100%"), ("display", "inline-block")]
+                  }
+                )
+                [ button
+                  (pure dats'
+                    { _simple   = singleton "id" "incr"
+                    , _class    = S.singleton "dim"
+                    , _handlers = singleton
+                      "click"
+                      (\_ s -> do
+                        (consoleLog browser)
+                          $  "Here is the current state "
+                          <> show s
+                        concept    <- randAbstract (random01 browser)
+                        comparedTo <- randConcrete (random01 browser)
+                        let
+                          newS = s
+                            { _abstractToConcrete = (concept, comparedTo)
+                                                      : abstractToConcrete
+                            }
+                        (consoleLog browser)
+                          $  "Here is the new state "
+                          <> show newS
+                        return $ newS
+                      )
+                    }
+                  )
+                  [txt "More aphorisms"]
+                , button
+                  (pure dats'
+                    { _simple   = singleton "id" "decr"
+                    , _class    = S.singleton "dim"
+                    , _handlers = singleton
+                      "click"
+                      (\_ s -> pure $ s
+                        { _abstractToConcrete = if (null abstractToConcrete)
+                                                  then []
+                                                  else tail abstractToConcrete
+                        }
+                      )
+                    }
+                  )
+                  [txt "Less aphorisms"]
+                ]
+              , inputF
+              , p_
+                [ txt "Logged in as: "
+                , span (pure dats' { _class = S.singleton "username" }) [txt name]
+                ]
+              ]
+          ]
+        )
+        <$> _abstractToConcrete
+        <*> _name
+  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
+
+
+a_n :: String -> String
+a_n 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;
+	}
+}
+  |]
+
+# else
+main :: IO ()
+main = print "If you're using ahc, please set -DPLZWRK_ENABLE_ASTERIUS as a flag to run this executable."
+# endif
+ kitchen-sink/Nouns.hs view
@@ -0,0 +1,519 @@+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
@@ -0,0 +1,117 @@+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.31.2.+--+-- see: https://github.com/sol/hpack+--+-- hash: 8099ceb0d406f862d89306de053aba4c75999a9e0d74ac6a502458d503e7dcc1++name:           plzwrk+version:        0.0.0.0+category:       Web+synopsis:        A front-end framework+description:    Please see the README on GitHub at <https://github.com/meeshkan/plzwrk#readme>+homepage:       https://github.com/meeshkan/plzwrk#readme+bug-reports:    https://github.com/meeshkan/plzwrk/issues+author:         Mike Solomon+maintainer:     mike@meeshkan.com+copyright:      2020 Mike Solomon+license:        BSD3+license-file:   LICENSE+build-type:     Simple+extra-source-files:+    README.md+    ChangeLog.md++source-repository head+  type: git+  location: https://github.com/meeshkan/plzwrk++flag plzwrk-enable-asterius+  Description: Enable asterius+  Default:     False+  Manual:      True++library+  exposed-modules:+      Web.Framework.Plzwrk+    , Web.Framework.Plzwrk.Asterius+    , Web.Framework.Plzwrk.MockJSVal+    , Web.Framework.Plzwrk.Tag+  other-modules:+      Paths_plzwrk+    , Web.Framework.Plzwrk.Base+    , Web.Framework.Plzwrk.Browserful+    , Web.Framework.Plzwrk.Domify+  hs-source-dirs:+      src+  build-depends:+      base >=4.7 && <5+    , aeson >= 1.4.7 && < 1.5+    , bytestring >= 0.10.10 && < 0.11+    , containers >= 0.6.2 && < 0.7+    , mtl >= 2.2.2 && < 2.3+    , random >= 1.1 && < 1.2+    , text >= 1.2.3 && < 1.3+    , transformers >= 0.5.6 && < 0.6+    , unordered-containers >= 0.2.10 && < 0.3+  default-language: Haskell2010+  if flag(plzwrk-enable-asterius)+    cpp-options:+      -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+  main-is: Spec.hs+  other-modules:+      Paths_plzwrk+  hs-source-dirs:+      test+  ghc-options: -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      base >=4.7 && <5+    , hspec >=2.7.0 && <2.7.1+    , mtl >=2.2.2 && <2.3+    , plzwrk+    , text >=1.2.3 && <1.3+    , unordered-containers >=0.2.10 && <0.3+  default-language: Haskell2010
+ src/Web/Framework/Plzwrk.hs view
@@ -0,0 +1,38 @@+{-|
+Module      : Web.Framework.Plzwrk
+Description : Base functions for plzwrk
+Copyright   : (c) Mike Solomon 2020
+License     : GPL-3
+Maintainer  : mike@meeshkan.com
+Stability   : experimental
+Portability : POSIX, Windows
+
+This module contains the base functions for plzwrk, notably
+the family of plzwrk functions needed for plzwrk to work. It
+also exports most of the utility functions used for building
+web applications, like event handling and attribute wrangling.
+-}
+
+module Web.Framework.Plzwrk
+  ( hydrate
+  , dats
+  , dats'
+  , Node(..)
+  , HydratedNode(..)
+  , Attributes(..)
+  , cssToStyle
+  , Browserful(..)
+  , reconcile
+  , plzwrk
+  , plzwrk'
+  , plzwrk'_
+  , OldStuff(..)
+  )
+where
+
+-- need to hide div from prelude
+
+import           Prelude                 hiding ( div )
+import           Web.Framework.Plzwrk.Base
+import           Web.Framework.Plzwrk.Browserful
+import           Web.Framework.Plzwrk.Domify
+ src/Web/Framework/Plzwrk/Asterius.hs view
@@ -0,0 +1,209 @@+{-# LANGUAGE CPP #-}
+#if defined(PLZWRK_ENABLE_ASTERIUS)
+{-# LANGUAGE InterruptibleFFI  #-}
+module Web.Framework.Plzwrk.Asterius (asteriusBrowser) where
+
+import Asterius.Aeson
+import           Asterius.ByteString
+import           Asterius.Types
+import qualified Data.ByteString        as BS
+import           Data.ByteString.Unsafe
+import           Data.Coerce
+import           Foreign.Ptr
+import           Web.Framework.Plzwrk.Browserful
+
+asteriusBrowser :: IO (Browserful JSVal)
+asteriusBrowser = return Browserful
+  { addEventListener    = _addEventListener
+  , appendChild         = _appendChild
+  , click               = _click
+  , consoleLog          = _consoleLog
+  , consoleLog'         = _consoleLog'
+  , createElement       = _createElement
+  , createTextNode      = _createTextNode
+  , freeCallback        = _freeCallback
+  , getBody             = _getBody
+  , getBool             = _getBool
+  , getDouble           = _getDouble
+  , getChildren         = _getChildren
+  , getElementById      = _getElementById
+  , getHead             = _getHead
+  , getInt              = _getInt
+  , getOpaque           = _getOpaque
+  , getString           = _getString
+  , getTag              = _getTag
+  , insertBefore        = _insertBefore
+  , invokeOn            = _invokeOn
+  , makeHaskellCallback = _makeHaskellCallback
+  , random01            = _random01
+  , removeChild         = _removeChild
+  , removeEventListener = _removeEventListener
+  , setAttribute        = _setAttribute
+  , textContent         = _textContent
+  }
+
+_createElement :: String -> IO JSVal
+_createElement = js_createElement . toJSString
+
+_getTag :: JSVal -> IO String
+_getTag x =  do
+  v <- js_getTag x
+  return $ fromJSString v
+
+_textContent :: JSVal -> IO String
+_textContent x =  do
+  v <- js_textContent x
+  return $ fromJSString v
+
+_setAttribute :: JSVal -> String -> String -> IO ()
+_setAttribute e k v = js_setAttribute e (toJSString k) (toJSString v)
+
+_getOpaque :: JSVal -> String -> IO (Maybe JSVal)
+_getOpaque n k = do
+  isUndef <- js_null_or_undef n
+  if isUndef then pure Nothing else (do
+      v <- _js_getOpaque n (toJSString k)
+      isUndef' <- js_null_or_undef v
+      if isUndef' then pure Nothing else pure (Just v)
+    )
+
+_getString :: JSVal -> String -> IO (Maybe String)
+_getString n k = _getGeneric (\v -> (jsonFromJSVal v) :: Either String String) n k
+
+_getBool :: JSVal -> String -> IO (Maybe Bool)
+_getBool n k = _getGeneric (\v -> (jsonFromJSVal v) :: Either String Bool) n k
+
+_getInt :: JSVal -> String -> IO (Maybe Int)
+_getInt n k = _getGeneric (\v -> (jsonFromJSVal v) :: Either String Int) n k
+
+_getDouble :: JSVal -> String -> IO (Maybe Double)
+_getDouble n k = _getGeneric (\v -> (jsonFromJSVal v) :: Either String Double) n k
+
+_getGeneric :: (JSVal -> Either String a) -> JSVal -> String -> IO (Maybe a)
+_getGeneric f n k = do
+  isUndef <- js_null_or_undef n
+  if isUndef then pure Nothing else (do
+    v <- _js_getOpaque n (toJSString k)
+    isUndef' <- js_null_or_undef v
+    if isUndef' then pure Nothing else (
+        let q = f v in
+        either (\_ -> pure Nothing) (pure . Just) q)
+      )
+
+_consoleLog :: String -> IO ()
+_consoleLog t = _js_consoleLog (toJSString t)
+
+_consoleLog' :: JSVal -> IO ()
+_consoleLog' v = _js_consoleLog' v
+
+
+_addEventListener :: JSVal -> String -> JSVal -> IO ()
+_addEventListener target event callback =
+  js_addEventListener target (toJSString event) callback
+
+_removeEventListener :: JSVal -> String -> JSVal -> IO ()
+_removeEventListener target event callback =
+  js_removeEventListener target (toJSString event) callback
+
+_createTextNode :: String -> IO JSVal
+_createTextNode = js_createTextNode . toJSString
+
+_invokeOn :: JSVal -> String -> IO ()
+_invokeOn e s = _js_invokeOn e (toJSString s)
+
+
+_getElementById :: String -> IO (Maybe JSVal)
+_getElementById k = do
+  v <- js_getElementById (toJSString k)
+  u <- js_null_or_undef v
+  return $ if u then Nothing else Just v
+
+getJSVal :: JSFunction -> JSVal
+getJSVal (JSFunction x) = x
+
+_makeHaskellCallback :: (JSVal -> IO ()) -> IO JSVal
+_makeHaskellCallback a = do
+  x <- makeHaskellCallback1 a
+  return $ getJSVal x
+
+_freeCallback :: JSVal -> IO ()
+_freeCallback v = freeHaskellCallback (JSFunction v)
+
+foreign import javascript "console.log($1)"
+  _js_consoleLog :: JSString -> IO ()
+
+foreign import javascript "console.log($1)"
+  _js_consoleLog' :: JSVal -> IO ()
+
+
+foreign import javascript "$1[$2]()"
+  _js_invokeOn :: JSVal -> JSString -> IO ()
+
+foreign import javascript "$1[$2]"
+  _js_getOpaque :: JSVal -> JSString -> IO JSVal
+
+foreign import javascript "document.createElement($1)"
+  js_createElement :: JSString -> IO JSVal
+
+foreign import javascript "Math.random()"
+  _random01 :: IO Double
+
+foreign import javascript "document.body"
+  _getBody :: IO JSVal
+
+foreign import javascript "document.head"
+  _getHead :: IO JSVal
+
+foreign import javascript "$1.tagName"
+  js_getTag :: JSVal -> IO JSString
+
+foreign import javascript "$1.textContent"
+  js_textContent :: JSVal -> IO JSString
+
+foreign import javascript "$1.setAttribute($2,$3)"
+  js_setAttribute :: JSVal -> JSString -> JSString -> IO ()
+
+foreign import javascript "$1.appendChild($2)"
+  _appendChild :: JSVal -> JSVal -> IO ()
+
+foreign import javascript "($1 == null) || ($1 == undefined)"
+  js_null_or_undef :: JSVal -> IO Bool
+
+foreign import javascript "$1.childNodes"
+  _js_getChildren :: JSVal -> IO JSArray
+
+_getChildren :: JSVal -> IO [JSVal]
+_getChildren x = do
+  v <- _js_getChildren x
+  return $ fromJSArray v
+
+foreign import javascript "$1.click()"
+  _click :: JSVal -> IO ()
+
+foreign import javascript "$1.insertBefore($2,$3)"
+  _insertBefore :: JSVal -> JSVal -> JSVal -> IO ()
+
+foreign import javascript "$1.removeChild($2)"
+  _removeChild :: JSVal -> JSVal -> IO ()
+
+foreign import javascript "$1.addEventListener($2,$3)"
+  js_addEventListener :: JSVal -> JSString -> JSVal -> IO ()
+
+foreign import javascript "$1.removeEventListener($2,$3)"
+  js_removeEventListener :: JSVal -> JSString -> JSVal -> IO ()
+
+foreign import javascript "document.createTextNode($1)"
+  js_createTextNode :: JSString -> IO JSVal
+
+foreign import javascript "document.getElementById($1)"
+  js_getElementById :: JSString -> IO JSVal
+
+foreign import javascript "wrapper oneshot"
+  makeHaskellCallback1 :: (JSVal -> IO ()) -> IO JSFunction
+
+# else
+module Web.Framework.Plzwrk.Asterius where
+
+ignoreMe :: IO ()
+ignoreMe = print "ignore me"
+# endif
+ src/Web/Framework/Plzwrk/Base.hs view
@@ -0,0 +1,68 @@+module Web.Framework.Plzwrk.Base
+  ( hydrate
+  , dats
+  , dats'
+  , Node(..)
+  , HydratedNode(..)
+  , Attributes(..)
+  , cssToStyle
+  )
+where
+
+import           Data.List
+
+import           Data.HashMap.Strict
+import           Data.Set                hiding ( empty
+                                                , toList
+                                                )
+import qualified Data.Set                      as S
+
+cssToStyle :: (HashMap String String) -> String
+cssToStyle css =
+  (intercalate ";" $ fmap (\(x, y) -> x <> ":" <> y) (toList css))
+
+-- data classes
+
+data Attributes s opq = MkAttributes
+  { _style   :: HashMap String String
+  , _class   :: Set String
+  , _simple  :: HashMap String String
+  , _handlers :: HashMap String (opq -> s -> IO s)
+  }
+
+dats = (\_ -> MkAttributes empty S.empty empty empty)
+dats' = MkAttributes empty S.empty empty empty
+
+
+instance Show (Attributes s opq) where
+  show (MkAttributes __style __class __simple _) =
+    "Attributes ("
+      <> show __style
+      <> ", "
+      <> show __class
+      <> ", "
+      <> show __simple
+      <> ")"
+
+data Node s opq = Element String (s -> Attributes s opq) [s -> Node s opq]
+    | TextNode String
+
+instance Show (Node s opq) where
+  show (Element t _ _) = show t
+  show (TextNode t   ) = show t
+
+data HydratedNode s opq = HydratedElement
+    { _hy_tag  :: String
+    , _hy_attr :: (Attributes s opq)
+    , _hy_kids :: [HydratedNode s opq]
+    }
+    | HydratedTextNode String
+    deriving (Show)
+
+_hydrate :: s -> Node s opq -> HydratedNode s opq
+_hydrate s (Element a b c) =
+  HydratedElement a (b s) (fmap (\x -> hydrate s x) c)
+_hydrate s (TextNode t) = HydratedTextNode t
+
+hydrate :: s -> (s -> Node s opq) -> HydratedNode s opq
+hydrate s f = _hydrate s (f s)
+ src/Web/Framework/Plzwrk/Browserful.hs view
@@ -0,0 +1,33 @@+module Web.Framework.Plzwrk.Browserful
+  ( Browserful(..)
+  )
+where
+
+data Browserful jsval = Browserful
+  { addEventListener    :: jsval -> String -> jsval -> IO ()
+  , appendChild         :: jsval -> jsval -> IO ()
+  , consoleLog          :: String -> IO ()
+  , consoleLog'         :: jsval -> IO ()
+  , click               :: jsval -> IO ()
+  , createElement       :: String -> IO jsval
+  , createTextNode      :: String -> IO jsval
+  , freeCallback        :: jsval -> IO ()
+  , getBody             :: IO jsval
+  , getBool             :: jsval -> String -> IO (Maybe Bool)
+  , getChildren         :: jsval -> IO [jsval]
+  , getDouble           :: jsval -> String -> IO (Maybe Double)
+  , getHead             :: IO jsval
+  , getElementById      :: String -> IO (Maybe jsval)
+  , getInt              :: jsval -> String -> IO (Maybe Int)
+  , getOpaque           :: jsval -> String -> IO (Maybe jsval)
+  , getString           :: jsval -> String -> IO (Maybe String)
+  , getTag              :: jsval -> IO String
+  , insertBefore        :: jsval -> jsval -> jsval -> IO ()
+  , invokeOn            :: jsval -> String -> IO ()
+  , makeHaskellCallback :: (jsval -> IO ()) -> IO jsval
+  , random01            :: IO Double
+  , removeChild         :: jsval -> jsval -> IO ()
+  , removeEventListener :: jsval -> String -> jsval -> IO ()
+  , setAttribute        :: jsval -> String -> String -> IO ()
+  , textContent         :: jsval -> IO String
+  }
+ src/Web/Framework/Plzwrk/Domify.hs view
@@ -0,0 +1,346 @@+module Web.Framework.Plzwrk.Domify
+  ( reconcile
+  , plzwrk
+  , plzwrk'
+  , plzwrk'_
+  , OldStuff(..)
+  )
+where
+
+import           Control.Applicative
+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
+
+data DomifiedAttributes jsval = MkDomifiedAttributes
+  { _d_style     :: HM.HashMap String String
+  , _d_class     :: S.Set String
+  , _d_simple    :: HM.HashMap String String
+  , _d_handlers  :: HM.HashMap String jsval
+  }
+
+data DomifiedNode jsval = DomifiedElement
+    { _dom_tag  :: String
+    , _dom_attr :: (DomifiedAttributes jsval)
+    , _dom_kids :: [DomifiedNode jsval]
+    , _dom_ptr  :: jsval
+    }
+    | DomifiedTextNode String jsval
+
+data OldStuff state jsval = OldStuff {
+  _oldState :: state,
+  _oldDom :: Maybe (DomifiedNode jsval)
+}
+
+---------- reader functions
+
+
+
+freeAttrFunctions
+  :: DomifiedAttributes jsval -> ReaderT (Browserful jsval) IO ()
+freeAttrFunctions (MkDomifiedAttributes _ _ _ __d_handlers) = do
+  _freeCallback <- asks freeCallback
+  liftIO $ void (mapM _freeCallback (HM.elems __d_handlers))
+
+freeFunctions :: DomifiedNode jsval -> ReaderT (Browserful jsval) IO ()
+freeFunctions (DomifiedElement _ b c _) = do
+  freeAttrFunctions b
+  mapM_ freeFunctions c
+freeFunctions _ = pure ()
+
+nodesEq
+  :: String
+  -> String
+  -> DomifiedAttributes jsval
+  -> Attributes state jsval
+  -> Bool
+nodesEq t0 t1 (MkDomifiedAttributes __d_style __d_class __d_simple _) (MkAttributes __style __class __simple _)
+  = (t0 == t1)
+    && (__d_style == __style)
+    && (__d_class == __class)
+    && (__d_simple == __simple)
+
+padr :: Int -> a -> [a] -> [a]
+padr i v l = if (length l >= i) then l else padr i v (l ++ [v])
+
+reconcile
+  :: IORef (OldStuff state jsval)
+  -> (state -> Node state jsval)
+  -> jsval
+  -> jsval
+  -> Maybe (DomifiedNode jsval)
+  -> Maybe (HydratedNode state jsval)
+  -> ReaderT
+       (Browserful jsval)
+       IO
+       (Maybe (DomifiedNode jsval))
+reconcile refToOldStuff domCreationF parentNode topLevelNode (Just (DomifiedElement currentTag currentAttributes currentChildren currentNode)) (Just maybeNewNode@(HydratedElement maybeNewTag maybeNewAttributes maybeNewChildren))
+  = if (nodesEq currentTag maybeNewTag currentAttributes maybeNewAttributes)
+    then
+      (do
+-- the tags and attributes are equal
+
+
+        let maxlen = max (length maybeNewChildren) (length currentChildren)
+        newChildren <- sequence $ getZipList
+          (   (reconcile refToOldStuff domCreationF currentNode topLevelNode)
+          <$> (ZipList (padr maxlen Nothing (fmap Just currentChildren)))
+          <*> (ZipList (padr maxlen Nothing (fmap Just maybeNewChildren)))
+          )
+        -- make new attributes to set event handlers
+
+
+        currentAttributes <- hydratedAttrsToDomifiedAttrs refToOldStuff
+                                                          domCreationF
+                                                          parentNode
+                                                          maybeNewAttributes
+        removeEventHandlers currentNode currentAttributes
+        setEventHandlers currentNode currentAttributes
+        return $ Just
+          (DomifiedElement currentTag
+                           currentAttributes
+                           (catMaybes newChildren)
+                           currentNode
+          )
+      )
+    else
+      (do
+        res <- domify refToOldStuff
+                      domCreationF
+                      parentNode
+                      topLevelNode
+                      (Just currentNode)
+                      maybeNewNode
+        return $ Just res
+      )
+reconcile refToOldStuff domCreationF parentNode topLevelNode (Just currentDomifiedString@(DomifiedTextNode currentString currentNode)) (Just maybeNewNode@(HydratedTextNode maybeNewString))
+  = if (currentString == maybeNewString)
+    then pure (Just currentDomifiedString)
+    else
+      (do
+        res <- domify refToOldStuff
+                      domCreationF
+                      parentNode
+                      topLevelNode
+                      (Just currentNode)
+                      maybeNewNode
+        return $ Just res
+      )
+reconcile refToOldStuff domCreationF parentNode topLevelNode (Just (DomifiedElement _ _ _ currentNode)) (Just maybeNewNode@(HydratedTextNode _))
+  = do
+    res <- domify refToOldStuff
+                  domCreationF
+                  parentNode
+                  topLevelNode
+                  (Just currentNode)
+                  maybeNewNode
+    return $ Just res
+reconcile refToOldStuff domCreationF parentNode topLevelNode (Just (DomifiedTextNode _ currentNode)) (Just maybeNewNode@(HydratedElement _ _ _))
+  = do
+    res <- domify refToOldStuff
+                  domCreationF
+                  parentNode
+                  topLevelNode
+                  (Just currentNode)
+                  maybeNewNode
+    return $ Just res
+reconcile refToOldStuff domCreationF parentNode topLevelNode Nothing (Just maybeNewNode)
+  = do
+    res <- domify refToOldStuff
+                  domCreationF
+                  parentNode
+                  topLevelNode
+                  Nothing
+                  maybeNewNode
+    return $ Just res
+reconcile refToOldStuff domCreationF parentNode _ (Just (DomifiedElement _ _ _ currentNode)) Nothing
+  = do
+    _removeChild <- asks removeChild
+    liftIO $ _removeChild parentNode currentNode
+    return Nothing
+reconcile refToOldStuff domCreationF parentNode _ (Just (DomifiedTextNode _ currentNode)) Nothing
+  = do
+    _removeChild <- asks removeChild
+    liftIO $ _removeChild parentNode currentNode
+    return Nothing
+reconcile _ _ _ _ _ _ = error "Inconsistent state"
+
+cbMaker
+  :: IORef (OldStuff state jsval)
+  -> (state -> Node 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
+    (reconcile 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 -> Node 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)
+
+hydratedAttrsToDomifiedAttrs
+  :: IORef (OldStuff state jsval)
+  -> (state -> Node state jsval)
+  -> jsval
+  -> Attributes state jsval
+  -> ReaderT (Browserful jsval) IO (DomifiedAttributes jsval)
+hydratedAttrsToDomifiedAttrs refToOldStuff domCreationF topLevelNode (MkAttributes __style __class __simple __handlers)
+  = do
+    handlers <- mapM
+      (\(k, v) -> do
+        func <- eventable refToOldStuff domCreationF topLevelNode v
+        return $ (k, func)
+      )
+      (HM.toList __handlers)
+    return
+      $ MkDomifiedAttributes __style __class __simple (HM.fromList handlers)
+
+setAtts :: jsval -> DomifiedAttributes jsval -> ReaderT (Browserful jsval) IO ()
+setAtts currentNode domifiedAttributes@(MkDomifiedAttributes __style __class __simple _)
+  = do
+    _setAttribute <- asks setAttribute
+    liftIO $ if (HM.null __style)
+      then (pure ())
+      else (_setAttribute currentNode "style") . cssToStyle $ __style
+    liftIO $ if (S.null __class)
+      then (pure ())
+      else ((_setAttribute currentNode "class") . unwords . S.toList) $ __class
+    liftIO $ mapM_ (\x -> _setAttribute currentNode (fst x) (snd x))
+                   (HM.toList __simple)
+    setEventHandlers currentNode domifiedAttributes
+
+handleOnlyEventListeners
+  :: (jsval -> String -> jsval -> IO ())
+  -> jsval
+  -> DomifiedAttributes jsval
+  -> IO ()
+handleOnlyEventListeners eventListenerHandlerF currentNode domifiedAttributes =
+  void $ mapM (\(k, v) -> eventListenerHandlerF currentNode k v)
+              (HM.toList . _d_handlers $ domifiedAttributes)
+
+setEventHandlers
+  :: jsval -> DomifiedAttributes jsval -> ReaderT (Browserful jsval) IO ()
+setEventHandlers currentNode domifiedAttributes = do
+  _addEventListener <- asks addEventListener
+  liftIO $ handleOnlyEventListeners _addEventListener
+                                    currentNode
+                                    domifiedAttributes
+
+removeEventHandlers
+  :: jsval -> DomifiedAttributes jsval -> ReaderT (Browserful jsval) IO ()
+removeEventHandlers currentNode domifiedAttributes = do
+  _removeEventListener <- asks removeEventListener
+  liftIO $ handleOnlyEventListeners _removeEventListener
+                                    currentNode
+                                    domifiedAttributes
+
+domify
+  :: IORef (OldStuff state jsval)
+  -> (state -> Node state jsval)
+  -> jsval
+  -> jsval
+  -> Maybe jsval
+  -> HydratedNode state jsval
+  -> ReaderT (Browserful jsval) IO (DomifiedNode jsval)
+domify refToOldStuff domCreationF parentNode topLevelNode replacing (HydratedElement tag attrs children)
+  = do
+    _createElement <- asks createElement
+    _appendChild   <- asks appendChild
+    _insertBefore  <- asks insertBefore
+    _removeChild   <- asks removeChild
+    newNode        <- liftIO $ _createElement tag
+    newAttributes  <- hydratedAttrsToDomifiedAttrs refToOldStuff
+                                                   domCreationF
+                                                   topLevelNode
+                                                   attrs
+    setAtts newNode newAttributes
+    newChildren <- mapM
+      (domify refToOldStuff domCreationF newNode topLevelNode Nothing)
+      children
+    maybe
+      (liftIO $ _appendChild parentNode newNode)
+      (\x -> do
+        liftIO $ _insertBefore parentNode newNode x
+        liftIO $ _removeChild parentNode x
+      )
+      replacing
+    liftIO $ return (DomifiedElement tag newAttributes newChildren newNode)
+domify _ _ parentNode topLevelNode replacing (HydratedTextNode text) = do
+  _createElement  <- asks createElement
+  _appendChild    <- asks appendChild
+  _insertBefore   <- asks insertBefore
+  _removeChild    <- asks removeChild
+  _createTextNode <- asks createTextNode
+  newTextNode     <- liftIO $ _createTextNode text
+  maybe
+    (liftIO $ _appendChild parentNode newTextNode)
+    (\x -> do
+      liftIO $ _insertBefore parentNode newTextNode x
+      liftIO $ _removeChild parentNode x
+    )
+    replacing
+  liftIO $ return (DomifiedTextNode text newTextNode)
+
+plzwrk
+  :: (state -> Node state jsval) -> state -> Browserful jsval -> String -> IO ()
+plzwrk domF state env nodeId = do
+  refToOldStuff <- newIORef (OldStuff state Nothing)
+  parentNode    <- (getElementById env) nodeId
+  newDom        <- maybe
+    (error $ ("Cannot find node with id " <> nodeId))
+    (\x -> runReaderT
+      (reconcile refToOldStuff domF x x Nothing (Just $ hydrate state domF))
+      env
+    )
+    parentNode
+  writeIORef refToOldStuff (OldStuff state newDom)
+
+plzwrk' :: (state -> Node state jsval) -> state -> Browserful jsval -> IO ()
+plzwrk' domF state env = do
+  refToOldStuff <- newIORef (OldStuff state Nothing)
+  parentNode    <- (getBody env)
+  newDom        <- runReaderT
+    (reconcile refToOldStuff
+               domF
+               parentNode
+               parentNode
+               Nothing
+               (Just $ hydrate state domF)
+    )
+    env
+  writeIORef refToOldStuff (OldStuff state newDom)
+
+plzwrk'_ :: (Int -> Node Int jsval) -> Browserful jsval -> IO ()
+plzwrk'_ domF env = plzwrk' domF 0 env
+ src/Web/Framework/Plzwrk/MockJSVal.hs view
@@ -0,0 +1,483 @@+module Web.Framework.Plzwrk.MockJSVal
+  ( MockJSVal(..)
+  , makeMockBrowser
+  , defaultInternalBrowser
+  , makeMockBrowserWithContext
+  )
+where
+
+import           Data.Aeson                     ( FromJSON )
+import           Data.HashMap.Strict     hiding ( foldr
+                                                , null
+                                                )
+import           Data.IORef
+import           Data.List                      ( elemIndex )
+import           Prelude                 hiding ( lookup )
+import           System.Random
+import           Web.Framework.Plzwrk.Base
+import           Web.Framework.Plzwrk.Browserful
+
+data LogEvent = ListenerReceived String Int
+    | AddedAsListenerTo Int
+    | AttributeReceived String String
+    | ChildReceived Int
+    | AddedAsChildTo Int
+    | RemovedNode Int
+    | RemovedAsNodeFrom Int
+    | RemovedListener String Int
+    | RemovedAsListenerFrom Int
+    | CreatedElement Int
+    | CreatedTextNode Int
+    | InsertedChildBefore Int Int
+    | InsertedAsChildBefore Int Int
+    | ElementAddedBefore Int
+    | GotElementById
+    | MadeCallback Int
+    | FreeCallback Int
+    deriving (Show, Eq)
+
+
+data MockAttributes = MockAttributes
+  { _d_attrs  :: HashMap String String
+  , _d_events :: HashMap String MockJSVal
+  }
+  deriving Show
+
+data MockJSVal = MockJSElement Int String MockAttributes [MockJSVal] [LogEvent]
+    | MockJSTextNode Int String [LogEvent]
+    | MockJSFunction Int (MockJSVal -> IO ()) [LogEvent]
+    | MockJSObject Int (HashMap String MockJSVal) [LogEvent]
+    | MockJSString Int String [LogEvent]
+    | MockJSNumber Int Double [LogEvent]
+    | MockJSArray Int [MockJSVal] [LogEvent]
+    | MockMouseEvent Int
+
+instance Show MockJSVal where
+  show (MockJSElement a b c d e) =
+    show a
+      <> " "
+      <> " "
+      <> show b
+      <> " "
+      <> show c
+      <> " "
+      <> show d
+      <> " "
+      <> show e
+  show (MockJSTextNode a b c) = show a <> " " <> show b <> " " <> show c
+  show (MockJSFunction 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 (MockJSNumber   a b c) = show a <> " " <> show b <> " " <> show c
+  show (MockJSArray    a b c) = show a <> " " <> show b <> " " <> show c
+  show (MockMouseEvent a    ) = show a
+
+_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 (MockJSObject   a b _   ) log = MockJSObject a b log
+_withNewLog (MockJSString   a b _   ) log = MockJSString a b log
+_withNewLog (MockJSNumber   a b _   ) log = MockJSNumber a b log
+_withNewLog (MockJSArray    a b _   ) log = MockJSArray a b log
+
+_withNewAttrs :: MockJSVal -> MockAttributes -> MockJSVal
+_withNewAttrs (MockJSElement n tg _ chlds log) newat =
+  MockJSElement n tg newat chlds log
+_withNewAttrs a _ = a
+
+_withNewKids :: MockJSVal -> [MockJSVal] -> MockJSVal
+_withNewKids (MockJSElement n tg attrs _ log) newKids =
+  MockJSElement n tg attrs newKids log
+_withNewKids a _ = a
+
+_ptr :: MockJSVal -> Int
+_ptr (MockJSElement a _ _ _ _) = a
+_ptr (MockJSTextNode a _ _   ) = a
+_ptr (MockJSFunction a _ _   ) = a
+_ptr (MockJSObject   a _ _   ) = a
+_ptr (MockJSString   a _ _   ) = a
+_ptr (MockJSNumber   a _ _   ) = a
+_ptr (MockJSArray    a _ _   ) = a
+
+_addEventListener
+  :: MockJSVal
+  -> String
+  -> MockJSVal
+  -> IO (MockAttributes, [LogEvent], [LogEvent])
+_addEventListener (MockJSElement n _ (MockAttributes atts lstns) _ logn) evt fn@(MockJSFunction m _ logm)
+  = pure
+    $ ( MockAttributes atts $ insert evt fn lstns
+      , logn <> [ListenerReceived evt m]
+      , logm <> [AddedAsListenerTo n]
+      )
+_addEventListener _ _ _ = error "Can only add event listener to element"
+
+_setAttribute :: MockJSVal -> String -> String -> IO (MockAttributes, [LogEvent])
+_setAttribute (MockJSElement n _ (MockAttributes atts lstns) _ logn) nm attr =
+  pure
+    $ ( MockAttributes (insert nm attr atts) lstns
+      , logn <> [AttributeReceived nm attr]
+      )
+_setAttribute _ _ _ = error "Can only add event listener to element"
+
+_appendChild
+  :: MockJSVal -> MockJSVal -> IO ([MockJSVal], [LogEvent], [LogEvent])
+_appendChild (MockJSElement n _ _ kids logn) kid@(MockJSElement m _ _ _ logm) =
+  pure $ (kids <> [kid], logn <> [ChildReceived m], logm <> [AddedAsChildTo n])
+_appendChild (MockJSElement n _ _ kids logn) kid@(MockJSTextNode m _ logm) =
+  pure $ (kids <> [kid], logn <> [ChildReceived m], logm <> [AddedAsChildTo n])
+_appendChild _ _ = error "Can only append element to element"
+
+__removeChild
+  :: Int
+  -> [MockJSVal]
+  -> [LogEvent]
+  -> MockJSVal
+  -> Int
+  -> [LogEvent]
+  -> IO ([MockJSVal], [LogEvent], [LogEvent])
+__removeChild 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]
+        )
+  )
+  (elemIndex (_ptr kid) (fmap _ptr kids))
+
+_removeChild
+  :: MockJSVal -> MockJSVal -> IO ([MockJSVal], [LogEvent], [LogEvent])
+_removeChild (MockJSElement n _ _ kids logn) kid@(MockJSElement m _ _ _ logm) =
+  __removeChild n kids logn kid m logm
+_removeChild (MockJSElement n _ _ kids logn) kid@(MockJSTextNode m _ logm) =
+  __removeChild n kids logn kid m logm
+_removeChild _ _ = error "Can only remove element from element"
+
+_removeEventListener
+  :: MockJSVal
+  -> String
+  -> MockJSVal
+  -> IO (MockAttributes, [LogEvent], [LogEvent])
+_removeEventListener (MockJSElement n _ (MockAttributes atts lstns) _ logn) evt fn@(MockJSFunction 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]
+          )
+    )
+    (lookup evt lstns)
+_removeEventListener _ _ _ = error "Can only add event listener to element"
+
+_insertBeforeInternal
+  :: Int
+  -> [MockJSVal]
+  -> [LogEvent]
+  -> MockJSVal
+  -> Int
+  -> [LogEvent]
+  -> MockJSVal
+  -> Int
+  -> [LogEvent]
+  -> IO
+       ( [MockJSVal]
+       , [LogEvent]
+       , [LogEvent]
+       , [LogEvent]
+       )
+_insertBeforeInternal 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]
+        )
+  )
+  (elemIndex (_ptr existingI) (fmap _ptr kids))
+
+
+_insertBefore
+  :: MockJSVal
+  -> MockJSVal
+  -> MockJSVal
+  -> IO ([MockJSVal], [LogEvent], [LogEvent], [LogEvent])
+_insertBefore (MockJSElement n _ _ kids logn) newI@(MockJSElement m _ _ _ logm) existingI@(MockJSElement l _ _ _ logl)
+  = _insertBeforeInternal n kids logn newI m logm existingI l logl
+_insertBefore (MockJSElement n _ _ kids logn) newI@(MockJSTextNode m _ logm) existingI@(MockJSElement l _ _ _ logl)
+  = _insertBeforeInternal n kids logn newI m logm existingI l logl
+_insertBefore (MockJSElement n _ _ kids logn) newI@(MockJSElement m _ _ _ logm) existingI@(MockJSTextNode l _ logl)
+  = _insertBeforeInternal n kids logn newI m logm existingI l logl
+_insertBefore (MockJSElement n _ _ kids logn) newI@(MockJSTextNode m _ logm) existingI@(MockJSTextNode l _ logl)
+  = _insertBeforeInternal n kids logn newI m logm existingI l logl
+_insertBefore _ _ _ = error "Can only append element to element"
+
+_getTag :: MockJSVal -> IO String
+_getTag (MockJSElement _ tag _ _ _) = return tag
+_getTag _                           = error "Can only get tag of element"
+
+_textContent :: MockJSVal -> IO String
+_textContent (MockJSTextNode _ txt _) = return txt
+_textContent _ = error "Can only get text content of text node"
+
+
+_getChildren :: MockJSVal -> IO [Int]
+_getChildren (MockJSElement _ _ _ kids _) = return $ fmap _ptr kids
+_getChildren _ = error "Can only get children of element"
+
+_freeCallback :: MockJSVal -> IO [LogEvent]
+_freeCallback (MockJSFunction n _ log) = pure (log <> [FreeCallback n])
+_freeCallback _                        = error "Can only free function"
+
+dummyClick :: MockJSVal -> IO ()
+-- todo give real number
+
+dummyClick (MockJSFunction _ f _) = f $ MockMouseEvent (-1)
+
+
+_click :: MockJSVal -> IO ()
+_click (MockJSElement _ _ (MockAttributes _ evts) _ _) = do
+  let oc = lookup "click" evts
+  maybe (pure ()) (\x -> dummyClick x) oc
+
+_click _ = error "Can only free function"
+
+
+--------------
+
+
+data MockBrowserInternal = MockBrowserInternal
+  { unBrowser :: HashMap Int MockJSVal
+  , unCtr     :: Int
+  }
+  deriving Show
+
+look :: IORef MockBrowserInternal -> Int -> IO MockJSVal
+look env elt = do
+  r <- readIORef env
+  let bz = unBrowser r
+  maybe (error $ "Cannot find object pointer in env: " <> (show elt))
+        (\x -> return x)
+        (lookup elt bz)
+
+incr :: IORef MockBrowserInternal -> IO Int
+incr env = do
+  r <- readIORef env
+  let ctr = unCtr r
+  writeIORef env $ r { unCtr = ctr + 1 }
+  return ctr
+
+
+wrt :: IORef MockBrowserInternal -> Int -> MockJSVal -> IO ()
+wrt env elt v = do
+  r <- readIORef env
+  let bz = unBrowser r
+  writeIORef env $ r { unBrowser = insert elt v bz }
+
+_'addEventListener :: IORef MockBrowserInternal -> Int -> String -> Int -> IO ()
+_'addEventListener env elt evt fn = do
+  _elt                            <- look env elt
+  _fn                             <- look env fn
+  (newAttrs, newLogElt, newLogFn) <- _addEventListener _elt evt _fn
+  wrt env elt $ _withNewLog (_withNewAttrs _elt newAttrs) newLogElt
+  wrt env fn $ _withNewLog _fn newLogFn
+
+_'appendChild :: IORef MockBrowserInternal -> Int -> Int -> IO ()
+_'appendChild env parent kid = do
+  _parent                            <- look env parent
+  _kid                               <- look env kid
+  (newKids, newLogParent, newLogKid) <- _appendChild _parent _kid
+  wrt env parent $ _withNewLog (_withNewKids _parent newKids) newLogParent
+  wrt env kid $ _withNewLog _kid newLogKid
+
+_'createElement :: IORef MockBrowserInternal -> String -> IO Int
+_'createElement env tg = do
+  i <- incr env
+  let elt =
+        MockJSElement i tg (MockAttributes empty empty) [] [CreatedElement i]
+  wrt env i elt
+  return i
+
+_'random01 :: IORef MockBrowserInternal -> IO Double
+_'random01 _ = pure 0.5
+
+_'consoleLog :: IORef MockBrowserInternal -> String -> IO ()
+_'consoleLog _ txt = print txt
+
+_'consoleLog' :: IORef MockBrowserInternal -> Int -> IO ()
+_'consoleLog' _ v = print (show v)
+
+
+_'createTextNode :: IORef MockBrowserInternal -> String -> IO Int
+_'createTextNode env txt = do
+  i <- incr env
+  let elt = MockJSTextNode i txt [CreatedTextNode i]
+  wrt env i elt
+  return i
+
+_'getString :: IORef MockBrowserInternal -> Int -> String -> IO (Maybe String)
+_'getString env _ _ = pure Nothing -- not implemented yet
+
+_'getBool :: IORef MockBrowserInternal -> Int -> String -> IO (Maybe Bool)
+_'getBool env _ _ = pure Nothing -- not implemented yet
+
+_'getInt :: IORef MockBrowserInternal -> Int -> String -> IO (Maybe Int)
+_'getInt env _ _ = pure Nothing -- not implemented yet
+
+_'getDouble :: IORef MockBrowserInternal -> Int -> String -> IO (Maybe Double)
+_'getDouble env _ _ = pure Nothing -- not implemented yet
+
+_'getOpaque :: IORef MockBrowserInternal -> Int -> String -> IO (Maybe Int)
+_'getOpaque env _ _ = pure Nothing -- not implemented yet
+
+
+_'invokeOn :: IORef MockBrowserInternal -> Int -> String -> IO ()
+_'invokeOn env _ _ = pure () -- not implemented yet
+
+
+_'getTag :: IORef MockBrowserInternal -> Int -> IO String
+_'getTag env elt = do
+  _elt <- look env elt
+  _getTag _elt
+
+_'getChildren :: IORef MockBrowserInternal -> Int -> IO [Int]
+_'getChildren env elt = do
+  _elt <- look env elt
+  _getChildren _elt
+
+_'textContent :: IORef MockBrowserInternal -> Int -> IO String
+_'textContent env elt = do
+  _elt <- look env elt
+  _textContent _elt
+
+_'freeCallback :: IORef MockBrowserInternal -> Int -> IO ()
+_'freeCallback env fn = do
+  _fn    <- look env fn
+  newLog <- _freeCallback _fn
+  wrt env fn $ _withNewLog _fn newLog
+
+_'click :: IORef MockBrowserInternal -> Int -> IO ()
+_'click env elt = do
+  _elt <- look env elt
+  _click _elt
+
+idEq :: String -> MockJSVal -> Bool
+idEq txt (MockJSElement _ _ (MockAttributes atts _) _ _) =
+  Just txt == (lookup "id" atts)
+idEq _ _ = False
+
+_'getBody :: IORef MockBrowserInternal -> IO Int
+_'getBody ref = do
+  mb <- readIORef ref
+  let browser = unBrowser mb
+  pt <- maybe (error "No body.") (\x -> pure $ _ptr x) $ lookup 0 browser
+  return pt
+
+_'getHead :: IORef MockBrowserInternal -> IO Int
+_'getHead ref = pure (-1) -- need to implement in mock?
+
+_getElementByIdInternal :: MockJSVal -> String -> [Int]
+_getElementByIdInternal jsv@(MockJSElement _ _ _ ch _) txt = if (idEq txt jsv)
+  then [_ptr jsv]
+  else (foldr (++) [] $ fmap (\x -> _getElementByIdInternal x txt) ch)
+_getElementByIdInternal _ _ = []
+
+_'getElementById :: IORef MockBrowserInternal -> String -> IO (Maybe Int)
+_'getElementById env txt = do
+  body  <- _'getBody env
+  _body <- look env body
+  let elts = _getElementByIdInternal _body txt
+  return $ if (null elts) then (Nothing) else (Just $ head elts)
+
+_'insertBefore :: IORef MockBrowserInternal -> Int -> Int -> Int -> IO ()
+_'insertBefore env parent newItem existingItem = do
+  _parent       <- look env parent
+  _newItem      <- look env newItem
+  _existingItem <- look env existingItem
+  (newKids, newLogParent, newLogNewItem, newLogExistingItem) <- _insertBefore
+    _parent
+    _newItem
+    _existingItem
+  wrt env parent $ _withNewLog (_withNewKids _parent newKids) newLogParent
+  wrt env newItem $ _withNewLog _newItem newLogNewItem
+  wrt env existingItem $ _withNewLog _existingItem newLogExistingItem
+
+_'makeHaskellCallback :: IORef MockBrowserInternal -> (Int -> IO ()) -> IO Int
+_'makeHaskellCallback env cb = do
+  i <- incr env
+  let elt = MockJSFunction i (\x -> cb $ _ptr x) [MadeCallback i]
+  wrt env i elt
+  return i
+
+_'removeChild :: IORef MockBrowserInternal -> Int -> Int -> IO ()
+_'removeChild env parent kid = do
+  _parent                            <- look env parent
+  _kid                               <- look env kid
+  (newKids, newLogParent, newLogKid) <- _removeChild _parent _kid
+  wrt env parent $ _withNewLog (_withNewKids _parent newKids) newLogParent
+  wrt env kid $ _withNewLog _kid newLogKid
+
+_'removeEventListener
+  :: IORef MockBrowserInternal -> Int -> String -> Int -> IO ()
+_'removeEventListener env elt evt fn = do
+  _elt                            <- look env elt
+  _fn                             <- look env fn
+  (newAttrs, newLogElt, newLogFn) <- _removeEventListener _elt evt _fn
+  wrt env elt $ _withNewLog (_withNewAttrs _elt newAttrs) newLogElt
+  wrt env fn $ _withNewLog _fn newLogFn
+
+_'setAttribute :: IORef MockBrowserInternal -> Int -> String -> String -> IO ()
+_'setAttribute env elt nm attr = do
+  _elt               <- look env elt
+  (newAttrs, newLog) <- _setAttribute _elt nm attr
+  wrt env elt $ _withNewLog (_withNewAttrs _elt newAttrs) newLog
+
+makeMockBrowserWithContext :: IORef MockBrowserInternal -> IO (Browserful Int)
+makeMockBrowserWithContext r = return Browserful
+  { addEventListener    = _'addEventListener r
+  , appendChild         = _'appendChild r
+  , consoleLog          = _'consoleLog r
+  , consoleLog'         = _'consoleLog' r
+  , click               = _'click r
+  , createElement       = _'createElement r
+  , createTextNode      = _'createTextNode r
+  , freeCallback        = _'freeCallback r
+  , getBody             = _'getBody r
+  , getBool             = _'getBool r
+  , getChildren         = _'getChildren r
+  , getDouble           = _'getDouble r
+  , getElementById      = _'getElementById r
+  , getHead             = _'getHead r
+  , getInt              = _'getInt r
+  , getOpaque           = _'getOpaque r
+  , getString           = _'getString r
+  , getTag              = _'getTag r
+  , insertBefore        = _'insertBefore r
+  , invokeOn            = _'invokeOn r
+  , makeHaskellCallback = _'makeHaskellCallback r
+  , random01            = _'random01 r
+  , removeChild         = _'removeChild r
+  , removeEventListener = _'removeEventListener r
+  , setAttribute        = _'setAttribute r
+  , textContent         = _'textContent r
+  }
+
+defaultInternalBrowser :: IO (IORef MockBrowserInternal)
+defaultInternalBrowser = do
+  let body = MockJSElement 0
+                           "body"
+                           (MockAttributes empty empty)
+                           []
+                           [CreatedElement 0]
+  newIORef MockBrowserInternal { unBrowser = singleton 0 body, unCtr = 1 }
+
+makeMockBrowser :: IO (Browserful Int)
+makeMockBrowser = do
+  rf <- defaultInternalBrowser
+  makeMockBrowserWithContext rf
+ src/Web/Framework/Plzwrk/Tag.hs view
@@ -0,0 +1,3051 @@+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+{-|
+Module      : Web.Framework.Plzwrk.Tag
+Description : Base functions for plzwrk
+Copyright   : (c) Mike Solomon 2020
+License     : GPL-3
+Maintainer  : mike@meeshkan.com
+Stability   : experimental
+Portability : POSIX, Windows
+
+This module contains tags for web development. It has stuff like
+@img@, @div@, @br@, @span@, etc. Because the module is huge, we
+recommend doing selective import of the tags you need.
+
+There are three conventions for tag naming:
+
+* tags that accept children, like @div@ and @p@
+* tags that do not have children but could have attributes, like @img@
+* tags that have no attributes and no children, like @br@
+
+For tags that can have children, the following six tags are exported
+(we'll use @div@ as an example, but the same works for @span@, @section@ etc):
+
+* @div@ : A div that does not need to be hydrated with a state.
+* @div'@ : A div that is hydrated with a state.
+* @div_@ : A div with no attributes that does not need to be hydrated with a state.
+* @div'_@ : A div with no attributes that is hydrated with a state.
+* @div__@ : A div that only contains text that does not need to be hydrated with a state.
+* @div'__@ : A div that only contains text that is hydrated with a state.
+
+For tags that do not have children, the following six tags are exported
+(we'll use @img@ as an example):
+
+* @img@ : A div that does not need to be hydrated with a state.
+* @img'@ : A div that is hydrated with a state.
+* @img_@ : A div with no attributes that does not need to be hydrated with a state.
+* @img'_@ : A div with no attributes that is hydrated with a state.
+
+For tags like br, there is only one export, namely @br@.
+
+Here are some gotchyas to bear in mind:
+
+* The HTML @data@ tag is renamed to @_data@ here.
+* Due to the volume of tags in this module, some of
+  them follow an incorrect convention, ie accepting children
+  when they shouldn't be able to. If you spot one, please
+  make a PR.
+-}
+module Web.Framework.Plzwrk.Tag( 
+a
+, a'
+, a_
+, a'_
+, a__
+, a'__
+, abbr
+, abbr'
+, abbr_
+, abbr'_
+, abbr__
+, abbr'__
+, acronym
+, acronym'
+, acronym_
+, acronym'_
+, acronym__
+, acronym'__
+, address
+, address'
+, address_
+, address'_
+, address__
+, address'__
+, applet
+, applet'
+, applet_
+, applet'_
+, applet__
+, applet'__
+, area
+, area'
+, area_
+, area'_
+, area__
+, area'__
+, article
+, article'
+, article_
+, article'_
+, article__
+, article'__
+, aside
+, aside'
+, aside_
+, aside'_
+, aside__
+, aside'__
+, audio
+, audio'
+, audio_
+, audio'_
+, audio__
+, audio'__
+, b
+, b'
+, b_
+, b'_
+, b__
+, b'__
+, base
+, base'
+, base_
+, base'_
+, base__
+, base'__
+, basefont
+, basefont'
+, basefont_
+, basefont'_
+, basefont__
+, basefont'__
+, bdi
+, bdi'
+, bdi_
+, bdi'_
+, bdi__
+, bdi'__
+, bdo
+, bdo'
+, bdo_
+, bdo'_
+, bdo__
+, bdo'__
+, big
+, big'
+, big_
+, big'_
+, big__
+, big'__
+, blockquote
+, blockquote'
+, blockquote_
+, blockquote'_
+, blockquote__
+, blockquote'__
+, body
+, body'
+, body_
+, body'_
+, body__
+, body'__
+, br
+, button
+, button'
+, button_
+, button'_
+, button__
+, button'__
+, canvas
+, canvas'
+, canvas_
+, canvas'_
+, canvas__
+, canvas'__
+, caption
+, caption'
+, caption_
+, caption'_
+, caption__
+, caption'__
+, center
+, center'
+, center_
+, center'_
+, center__
+, center'__
+, cite
+, cite'
+, cite_
+, cite'_
+, cite__
+, cite'__
+, code
+, code'
+, code_
+, code'_
+, code__
+, code'__
+, col
+, col'
+, col_
+, col'_
+, col__
+, col'__
+, colgroup
+, colgroup'
+, colgroup_
+, colgroup'_
+, colgroup__
+, colgroup'__
+, _data
+, _data'
+, _data_
+, _data'_
+, _data__
+, _data'__
+, _datalist
+, _datalist'
+, _datalist_
+, _datalist'_
+, _datalist__
+, _datalist'__
+, dd
+, dd'
+, dd_
+, dd'_
+, dd__
+, dd'__
+, del
+, del'
+, del_
+, del'_
+, del__
+, del'__
+, details
+, details'
+, details_
+, details'_
+, details__
+, details'__
+, dfn
+, dfn'
+, dfn_
+, dfn'_
+, dfn__
+, dfn'__
+, dialog
+, dialog'
+, dialog_
+, dialog'_
+, dialog__
+, dialog'__
+, dir
+, dir'
+, dir_
+, dir'_
+, dir__
+, dir'__
+, div
+, div'
+, div_
+, div'_
+, div__
+, div'__
+, dl
+, dl'
+, dl_
+, dl'_
+, dl__
+, dl'__
+, dt
+, dt'
+, dt_
+, dt'_
+, dt__
+, dt'__
+, em
+, em'
+, em_
+, em'_
+, em__
+, em'__
+, embed
+, embed'
+, embed_
+, embed'_
+, embed__
+, embed'__
+, fieldset
+, fieldset'
+, fieldset_
+, fieldset'_
+, fieldset__
+, fieldset'__
+, figcaption
+, figcaption'
+, figcaption_
+, figcaption'_
+, figcaption__
+, figcaption'__
+, figure
+, figure'
+, figure_
+, figure'_
+, figure__
+, figure'__
+, font
+, font'
+, font_
+, font'_
+, font__
+, font'__
+, footer
+, footer'
+, footer_
+, footer'_
+, footer__
+, footer'__
+, form
+, form'
+, form_
+, form'_
+, form__
+, form'__
+, frame
+, frame'
+, frame_
+, frame'_
+, frame__
+, frame'__
+, frameset
+, frameset'
+, frameset_
+, frameset'_
+, frameset__
+, frameset'__
+, h1
+, h1'
+, h1_
+, h1'_
+, h1__
+, h1'__
+, h2
+, h2'
+, h2_
+, h2'_
+, h2__
+, h2'__
+, h3
+, h3'
+, h3_
+, h3'_
+, h3__
+, h3'__
+, h4
+, h4'
+, h4_
+, h4'_
+, h4__
+, h4'__
+, h5
+, h5'
+, h5_
+, h5'_
+, h5__
+, h5'__
+, h6
+, h6'
+, h6_
+, h6'_
+, h6__
+, h6'__
+, head
+, head'
+, head_
+, head'_
+, head__
+, head'__
+, header
+, header'
+, header_
+, header'_
+, header__
+, header'__
+, hr
+, html
+, html'
+, html_
+, html'_
+, html__
+, html'__
+, i
+, i'
+, i_
+, i'_
+, i__
+, i'__
+, iframe
+, iframe'
+, iframe_
+, iframe'_
+, iframe__
+, iframe'__
+, img
+, img'
+, img_
+, img'_
+, input
+, input'
+, input_
+, input'_
+, input__
+, input'__
+, ins
+, ins'
+, ins_
+, ins'_
+, ins__
+, ins'__
+, kbd
+, kbd'
+, kbd_
+, kbd'_
+, kbd__
+, kbd'__
+, label
+, label'
+, label_
+, label'_
+, label__
+, label'__
+, legend
+, legend'
+, legend_
+, legend'_
+, legend__
+, legend'__
+, li
+, li'
+, li_
+, li'_
+, li__
+, li'__
+, link
+, link'
+, link_
+, link'_
+, link__
+, link'__
+, main
+, main'
+, main_
+, main'_
+, main__
+, main'__
+, map
+, map'
+, map_
+, map'_
+, map__
+, map'__
+, mark
+, mark'
+, mark_
+, mark'_
+, mark__
+, mark'__
+, meta
+, meta'
+, meta_
+, meta'_
+, meta__
+, meta'__
+, meter
+, meter'
+, meter_
+, meter'_
+, meter__
+, meter'__
+, nav
+, nav'
+, nav_
+, nav'_
+, nav__
+, nav'__
+, noframes
+, noframes'
+, noframes_
+, noframes'_
+, noframes__
+, noframes'__
+, noscript
+, noscript'
+, noscript_
+, noscript'_
+, noscript__
+, noscript'__
+, object
+, object'
+, object_
+, object'_
+, object__
+, object'__
+, ol
+, ol'
+, ol_
+, ol'_
+, ol__
+, ol'__
+, optgroup
+, optgroup'
+, optgroup_
+, optgroup'_
+, optgroup__
+, optgroup'__
+, option
+, option'
+, option_
+, option'_
+, option__
+, option'__
+, output
+, output'
+, output_
+, output'_
+, output__
+, output'__
+, p
+, p'
+, p_
+, p'_
+, p__
+, p'__
+, param
+, param'
+, param_
+, param'_
+, param__
+, param'__
+, picture
+, picture'
+, picture_
+, picture'_
+, picture__
+, picture'__
+, pre
+, pre'
+, pre_
+, pre'_
+, pre__
+, pre'__
+, progress
+, progress'
+, progress_
+, progress'_
+, progress__
+, progress'__
+, q
+, q'
+, q_
+, q'_
+, q__
+, q'__
+, rp
+, rp'
+, rp_
+, rp'_
+, rp__
+, rp'__
+, rt
+, rt'
+, rt_
+, rt'_
+, rt__
+, rt'__
+, ruby
+, ruby'
+, ruby_
+, ruby'_
+, ruby__
+, ruby'__
+, s
+, s'
+, s_
+, s'_
+, s__
+, s'__
+, samp
+, samp'
+, samp_
+, samp'_
+, samp__
+, samp'__
+, script
+, script'
+, script_
+, script'_
+, script__
+, script'__
+, section
+, section'
+, section_
+, section'_
+, section__
+, section'__
+, select
+, select'
+, select_
+, select'_
+, select__
+, select'__
+, small
+, small'
+, small_
+, small'_
+, small__
+, small'__
+, source
+, source'
+, source_
+, source'_
+, source__
+, source'__
+, span
+, span'
+, span_
+, span'_
+, span__
+, span'__
+, strike
+, strike'
+, strike_
+, strike'_
+, strike__
+, strike'__
+, strong
+, strong'
+, strong_
+, strong'_
+, strong__
+, strong'__
+, style
+, style'
+, style_
+, style'_
+, style__
+, style'__
+, sub
+, sub'
+, sub_
+, sub'_
+, sub__
+, sub'__
+, summary
+, summary'
+, summary_
+, summary'_
+, summary__
+, summary'__
+, sup
+, sup'
+, sup_
+, sup'_
+, sup__
+, sup'__
+, svg
+, svg'
+, svg_
+, svg'_
+, svg__
+, svg'__
+, table
+, table'
+, table_
+, table'_
+, table__
+, table'__
+, tbody
+, tbody'
+, tbody_
+, tbody'_
+, tbody__
+, tbody'__
+, td
+, td'
+, td_
+, td'_
+, td__
+, td'__
+, template
+, template'
+, template_
+, template'_
+, template__
+, template'__
+, textarea
+, textarea'
+, textarea_
+, textarea'_
+, textarea__
+, textarea'__
+, tfoot
+, tfoot'
+, tfoot_
+, tfoot'_
+, tfoot__
+, tfoot'__
+, th
+, th'
+, th_
+, th'_
+, th__
+, th'__
+, thead
+, thead'
+, thead_
+, thead'_
+, thead__
+, thead'__
+, time
+, time'
+, time_
+, time'_
+, time__
+, time'__
+, title
+, title'
+, title_
+, title'_
+, title__
+, title'__
+, tr
+, tr'
+, tr_
+, tr'_
+, tr__
+, tr'__
+, track
+, track'
+, track_
+, track'_
+, track__
+, track'__
+, tt
+, tt'
+, tt_
+, tt'_
+, tt__
+, tt'__
+, u
+, u'
+, u_
+, u'_
+, u__
+, u'__
+, ul
+, ul'
+, ul_
+, ul'_
+, ul__
+, ul'__
+, var
+, var'
+, var_
+, var'_
+, var__
+, var'__
+, video
+, video'
+, video_
+, video'_
+, video__
+, video'__
+, wbr
+, txt
+, txt'
+) where
+
+import Prelude(String)
+import Web.Framework.Plzwrk.Base
+
+type AFSig s opq
+  = (s -> Attributes s opq) -> [s -> Node s opq] -> (s -> Node s opq)
+type Sig s opq = (s -> Attributes s opq) -> [s -> Node s opq] -> Node s opq
+
+type AFSig_ s opq = [s -> Node s opq] -> (s -> Node s opq)
+type Sig_ s opq = [s -> Node s opq] -> Node s opq
+
+type AFSig__ s opq = String -> (s -> Node s opq)
+type Sig__ s opq = String -> Node s opq
+
+
+a :: AFSig s opq
+a x y = (\_ -> Element "a" x y)
+
+a' :: Sig s opq
+a' = Element "a"
+
+a_ :: AFSig_ s opq
+a_ x = (\_ -> Element "a" dats x)
+
+a'_ :: Sig_ s opq
+a'_ x = Element "a" dats x
+
+a__ :: AFSig__ s opq
+a__ x = (\_ -> Element "a" dats [txt x])
+
+a'__ :: Sig__ s opq
+a'__ x = Element "a" dats [txt x]
+
+
+abbr :: AFSig s opq
+abbr x y = (\_ -> Element "abbr" x y)
+
+abbr' :: Sig s opq
+abbr' = Element "abbr"
+
+abbr_ :: AFSig_ s opq
+abbr_ x = (\_ -> Element "abbr" dats x)
+
+abbr'_ :: Sig_ s opq
+abbr'_ x = Element "abbr" dats x
+
+abbr__ :: AFSig__ s opq
+abbr__ x = (\_ -> Element "abbr" dats [txt x])
+
+abbr'__ :: Sig__ s opq
+abbr'__ x = Element "abbr" dats [txt x]
+
+
+acronym :: AFSig s opq
+acronym x y = (\_ -> Element "acronym" x y)
+
+acronym' :: Sig s opq
+acronym' = Element "acronym"
+
+acronym_ :: AFSig_ s opq
+acronym_ x = (\_ -> Element "acronym" dats x)
+
+acronym'_ :: Sig_ s opq
+acronym'_ x = Element "acronym" dats x
+
+acronym__ :: AFSig__ s opq
+acronym__ x = (\_ -> Element "acronym" dats [txt x])
+
+acronym'__ :: Sig__ s opq
+acronym'__ x = Element "acronym" dats [txt x]
+
+
+address :: AFSig s opq
+address x y = (\_ -> Element "address" x y)
+
+address' :: Sig s opq
+address' = Element "address"
+
+address_ :: AFSig_ s opq
+address_ x = (\_ -> Element "address" dats x)
+
+address'_ :: Sig_ s opq
+address'_ x = Element "address" dats x
+
+address__ :: AFSig__ s opq
+address__ x = (\_ -> Element "address" dats [txt x])
+
+address'__ :: Sig__ s opq
+address'__ x = Element "address" dats [txt x]
+
+
+applet :: AFSig s opq
+applet x y = (\_ -> Element "applet" x y)
+
+applet' :: Sig s opq
+applet' = Element "applet"
+
+applet_ :: AFSig_ s opq
+applet_ x = (\_ -> Element "applet" dats x)
+
+applet'_ :: Sig_ s opq
+applet'_ x = Element "applet" dats x
+
+applet__ :: AFSig__ s opq
+applet__ x = (\_ -> Element "applet" dats [txt x])
+
+applet'__ :: Sig__ s opq
+applet'__ x = Element "applet" dats [txt x]
+
+
+area :: AFSig s opq
+area x y = (\_ -> Element "area" x y)
+
+area' :: Sig s opq
+area' = Element "area"
+
+area_ :: AFSig_ s opq
+area_ x = (\_ -> Element "area" dats x)
+
+area'_ :: Sig_ s opq
+area'_ x = Element "area" dats x
+
+area__ :: AFSig__ s opq
+area__ x = (\_ -> Element "area" dats [txt x])
+
+area'__ :: Sig__ s opq
+area'__ x = Element "area" dats [txt x]
+
+
+article :: AFSig s opq
+article x y = (\_ -> Element "article" x y)
+
+article' :: Sig s opq
+article' = Element "article"
+
+article_ :: AFSig_ s opq
+article_ x = (\_ -> Element "article" dats x)
+
+article'_ :: Sig_ s opq
+article'_ x = Element "article" dats x
+
+article__ :: AFSig__ s opq
+article__ x = (\_ -> Element "article" dats [txt x])
+
+article'__ :: Sig__ s opq
+article'__ x = Element "article" dats [txt x]
+
+
+aside :: AFSig s opq
+aside x y = (\_ -> Element "aside" x y)
+
+aside' :: Sig s opq
+aside' = Element "aside"
+
+aside_ :: AFSig_ s opq
+aside_ x = (\_ -> Element "aside" dats x)
+
+aside'_ :: Sig_ s opq
+aside'_ x = Element "aside" dats x
+
+aside__ :: AFSig__ s opq
+aside__ x = (\_ -> Element "aside" dats [txt x])
+
+aside'__ :: Sig__ s opq
+aside'__ x = Element "aside" dats [txt x]
+
+
+audio :: AFSig s opq
+audio x y = (\_ -> Element "audio" x y)
+
+audio' :: Sig s opq
+audio' = Element "audio"
+
+audio_ :: AFSig_ s opq
+audio_ x = (\_ -> Element "audio" dats x)
+
+audio'_ :: Sig_ s opq
+audio'_ x = Element "audio" dats x
+
+audio__ :: AFSig__ s opq
+audio__ x = (\_ -> Element "audio" dats [txt x])
+
+audio'__ :: Sig__ s opq
+audio'__ x = Element "audio" dats [txt x]
+
+
+b :: AFSig s opq
+b x y = (\_ -> Element "b" x y)
+
+b' :: Sig s opq
+b' = Element "b"
+
+b_ :: AFSig_ s opq
+b_ x = (\_ -> Element "b" dats x)
+
+b'_ :: Sig_ s opq
+b'_ x = Element "b" dats x
+
+b__ :: AFSig__ s opq
+b__ x = (\_ -> Element "b" dats [txt x])
+
+b'__ :: Sig__ s opq
+b'__ x = Element "b" dats [txt x]
+
+
+base :: AFSig s opq
+base x y = (\_ -> Element "base" x y)
+
+base' :: Sig s opq
+base' = Element "base"
+
+base_ :: AFSig_ s opq
+base_ x = (\_ -> Element "base" dats x)
+
+base'_ :: Sig_ s opq
+base'_ x = Element "base" dats x
+
+base__ :: AFSig__ s opq
+base__ x = (\_ -> Element "base" dats [txt x])
+
+base'__ :: Sig__ s opq
+base'__ x = Element "base" dats [txt x]
+
+
+basefont :: AFSig s opq
+basefont x y = (\_ -> Element "basefont" x y)
+
+basefont' :: Sig s opq
+basefont' = Element "basefont"
+
+basefont_ :: AFSig_ s opq
+basefont_ x = (\_ -> Element "basefont" dats x)
+
+basefont'_ :: Sig_ s opq
+basefont'_ x = Element "basefont" dats x
+
+basefont__ :: AFSig__ s opq
+basefont__ x = (\_ -> Element "basefont" dats [txt x])
+
+basefont'__ :: Sig__ s opq
+basefont'__ x = Element "basefont" dats [txt x]
+
+
+bdi :: AFSig s opq
+bdi x y = (\_ -> Element "bdi" x y)
+
+bdi' :: Sig s opq
+bdi' = Element "bdi"
+
+bdi_ :: AFSig_ s opq
+bdi_ x = (\_ -> Element "bdi" dats x)
+
+bdi'_ :: Sig_ s opq
+bdi'_ x = Element "bdi" dats x
+
+bdi__ :: AFSig__ s opq
+bdi__ x = (\_ -> Element "bdi" dats [txt x])
+
+bdi'__ :: Sig__ s opq
+bdi'__ x = Element "bdi" dats [txt x]
+
+
+bdo :: AFSig s opq
+bdo x y = (\_ -> Element "bdo" x y)
+
+bdo' :: Sig s opq
+bdo' = Element "bdo"
+
+bdo_ :: AFSig_ s opq
+bdo_ x = (\_ -> Element "bdo" dats x)
+
+bdo'_ :: Sig_ s opq
+bdo'_ x = Element "bdo" dats x
+
+bdo__ :: AFSig__ s opq
+bdo__ x = (\_ -> Element "bdo" dats [txt x])
+
+bdo'__ :: Sig__ s opq
+bdo'__ x = Element "bdo" dats [txt x]
+
+
+big :: AFSig s opq
+big x y = (\_ -> Element "big" x y)
+
+big' :: Sig s opq
+big' = Element "big"
+
+big_ :: AFSig_ s opq
+big_ x = (\_ -> Element "big" dats x)
+
+big'_ :: Sig_ s opq
+big'_ x = Element "big" dats x
+
+big__ :: AFSig__ s opq
+big__ x = (\_ -> Element "big" dats [txt x])
+
+big'__ :: Sig__ s opq
+big'__ x = Element "big" dats [txt x]
+
+
+blockquote :: AFSig s opq
+blockquote x y = (\_ -> Element "blockquote" x y)
+
+blockquote' :: Sig s opq
+blockquote' = Element "blockquote"
+
+blockquote_ :: AFSig_ s opq
+blockquote_ x = (\_ -> Element "blockquote" dats x)
+
+blockquote'_ :: Sig_ s opq
+blockquote'_ x = Element "blockquote" dats x
+
+blockquote__ :: AFSig__ s opq
+blockquote__ x = (\_ -> Element "blockquote" dats [txt x])
+
+blockquote'__ :: Sig__ s opq
+blockquote'__ x = Element "blockquote" dats [txt x]
+
+
+body :: AFSig s opq
+body x y = (\_ -> Element "body" x y)
+
+body' :: Sig s opq
+body' = Element "body"
+
+body_ :: AFSig_ s opq
+body_ x = (\_ -> Element "body" dats x)
+
+body'_ :: Sig_ s opq
+body'_ x = Element "body" dats x
+
+body__ :: AFSig__ s opq
+body__ x = (\_ -> Element "body" dats [txt x])
+
+body'__ :: Sig__ s opq
+body'__ x = Element "body" dats [txt x]
+
+
+br :: (s -> Node s opq)
+br = (\_ -> Element "br" dats [])
+
+button :: AFSig s opq
+button x y = (\_ -> Element "button" x y)
+
+button' :: Sig s opq
+button' = Element "button"
+
+button_ :: AFSig_ s opq
+button_ x = (\_ -> Element "button" dats x)
+
+button'_ :: Sig_ s opq
+button'_ x = Element "button" dats x
+
+button__ :: AFSig__ s opq
+button__ x = (\_ -> Element "button" dats [txt x])
+
+button'__ :: Sig__ s opq
+button'__ x = Element "button" dats [txt x]
+
+
+canvas :: AFSig s opq
+canvas x y = (\_ -> Element "canvas" x y)
+
+canvas' :: Sig s opq
+canvas' = Element "canvas"
+
+canvas_ :: AFSig_ s opq
+canvas_ x = (\_ -> Element "canvas" dats x)
+
+canvas'_ :: Sig_ s opq
+canvas'_ x = Element "canvas" dats x
+
+canvas__ :: AFSig__ s opq
+canvas__ x = (\_ -> Element "canvas" dats [txt x])
+
+canvas'__ :: Sig__ s opq
+canvas'__ x = Element "canvas" dats [txt x]
+
+
+caption :: AFSig s opq
+caption x y = (\_ -> Element "caption" x y)
+
+caption' :: Sig s opq
+caption' = Element "caption"
+
+caption_ :: AFSig_ s opq
+caption_ x = (\_ -> Element "caption" dats x)
+
+caption'_ :: Sig_ s opq
+caption'_ x = Element "caption" dats x
+
+caption__ :: AFSig__ s opq
+caption__ x = (\_ -> Element "caption" dats [txt x])
+
+caption'__ :: Sig__ s opq
+caption'__ x = Element "caption" dats [txt x]
+
+
+center :: AFSig s opq
+center x y = (\_ -> Element "center" x y)
+
+center' :: Sig s opq
+center' = Element "center"
+
+center_ :: AFSig_ s opq
+center_ x = (\_ -> Element "center" dats x)
+
+center'_ :: Sig_ s opq
+center'_ x = Element "center" dats x
+
+center__ :: AFSig__ s opq
+center__ x = (\_ -> Element "center" dats [txt x])
+
+center'__ :: Sig__ s opq
+center'__ x = Element "center" dats [txt x]
+
+
+cite :: AFSig s opq
+cite x y = (\_ -> Element "cite" x y)
+
+cite' :: Sig s opq
+cite' = Element "cite"
+
+cite_ :: AFSig_ s opq
+cite_ x = (\_ -> Element "cite" dats x)
+
+cite'_ :: Sig_ s opq
+cite'_ x = Element "cite" dats x
+
+cite__ :: AFSig__ s opq
+cite__ x = (\_ -> Element "cite" dats [txt x])
+
+cite'__ :: Sig__ s opq
+cite'__ x = Element "cite" dats [txt x]
+
+
+code :: AFSig s opq
+code x y = (\_ -> Element "code" x y)
+
+code' :: Sig s opq
+code' = Element "code"
+
+code_ :: AFSig_ s opq
+code_ x = (\_ -> Element "code" dats x)
+
+code'_ :: Sig_ s opq
+code'_ x = Element "code" dats x
+
+code__ :: AFSig__ s opq
+code__ x = (\_ -> Element "code" dats [txt x])
+
+code'__ :: Sig__ s opq
+code'__ x = Element "code" dats [txt x]
+
+
+col :: AFSig s opq
+col x y = (\_ -> Element "col" x y)
+
+col' :: Sig s opq
+col' = Element "col"
+
+col_ :: AFSig_ s opq
+col_ x = (\_ -> Element "col" dats x)
+
+col'_ :: Sig_ s opq
+col'_ x = Element "col" dats x
+
+col__ :: AFSig__ s opq
+col__ x = (\_ -> Element "col" dats [txt x])
+
+col'__ :: Sig__ s opq
+col'__ x = Element "col" dats [txt x]
+
+
+colgroup :: AFSig s opq
+colgroup x y = (\_ -> Element "colgroup" x y)
+
+colgroup' :: Sig s opq
+colgroup' = Element "colgroup"
+
+colgroup_ :: AFSig_ s opq
+colgroup_ x = (\_ -> Element "colgroup" dats x)
+
+colgroup'_ :: Sig_ s opq
+colgroup'_ x = Element "colgroup" dats x
+
+colgroup__ :: AFSig__ s opq
+colgroup__ x = (\_ -> Element "colgroup" dats [txt x])
+
+colgroup'__ :: Sig__ s opq
+colgroup'__ x = Element "colgroup" dats [txt x]
+
+
+_data :: AFSig s opq
+_data x y = (\_ -> Element "_data" x y)
+
+_data' :: Sig s opq
+_data' = Element "_data"
+
+_data_ :: AFSig_ s opq
+_data_ x = (\_ -> Element "_data" dats x)
+
+_data'_ :: Sig_ s opq
+_data'_ x = Element "_data" dats x
+
+_data__ :: AFSig__ s opq
+_data__ x = (\_ -> Element "_data" dats [txt x])
+
+_data'__ :: Sig__ s opq
+_data'__ x = Element "_data" dats [txt x]
+
+
+_datalist :: AFSig s opq
+_datalist x y = (\_ -> Element "_datalist" x y)
+
+_datalist' :: Sig s opq
+_datalist' = Element "_datalist"
+
+_datalist_ :: AFSig_ s opq
+_datalist_ x = (\_ -> Element "_datalist" dats x)
+
+_datalist'_ :: Sig_ s opq
+_datalist'_ x = Element "_datalist" dats x
+
+_datalist__ :: AFSig__ s opq
+_datalist__ x = (\_ -> Element "_datalist" dats [txt x])
+
+_datalist'__ :: Sig__ s opq
+_datalist'__ x = Element "_datalist" dats [txt x]
+
+
+dd :: AFSig s opq
+dd x y = (\_ -> Element "dd" x y)
+
+dd' :: Sig s opq
+dd' = Element "dd"
+
+dd_ :: AFSig_ s opq
+dd_ x = (\_ -> Element "dd" dats x)
+
+dd'_ :: Sig_ s opq
+dd'_ x = Element "dd" dats x
+
+dd__ :: AFSig__ s opq
+dd__ x = (\_ -> Element "dd" dats [txt x])
+
+dd'__ :: Sig__ s opq
+dd'__ x = Element "dd" dats [txt x]
+
+
+del :: AFSig s opq
+del x y = (\_ -> Element "del" x y)
+
+del' :: Sig s opq
+del' = Element "del"
+
+del_ :: AFSig_ s opq
+del_ x = (\_ -> Element "del" dats x)
+
+del'_ :: Sig_ s opq
+del'_ x = Element "del" dats x
+
+del__ :: AFSig__ s opq
+del__ x = (\_ -> Element "del" dats [txt x])
+
+del'__ :: Sig__ s opq
+del'__ x = Element "del" dats [txt x]
+
+
+details :: AFSig s opq
+details x y = (\_ -> Element "details" x y)
+
+details' :: Sig s opq
+details' = Element "details"
+
+details_ :: AFSig_ s opq
+details_ x = (\_ -> Element "details" dats x)
+
+details'_ :: Sig_ s opq
+details'_ x = Element "details" dats x
+
+details__ :: AFSig__ s opq
+details__ x = (\_ -> Element "details" dats [txt x])
+
+details'__ :: Sig__ s opq
+details'__ x = Element "details" dats [txt x]
+
+
+dfn :: AFSig s opq
+dfn x y = (\_ -> Element "dfn" x y)
+
+dfn' :: Sig s opq
+dfn' = Element "dfn"
+
+dfn_ :: AFSig_ s opq
+dfn_ x = (\_ -> Element "dfn" dats x)
+
+dfn'_ :: Sig_ s opq
+dfn'_ x = Element "dfn" dats x
+
+dfn__ :: AFSig__ s opq
+dfn__ x = (\_ -> Element "dfn" dats [txt x])
+
+dfn'__ :: Sig__ s opq
+dfn'__ x = Element "dfn" dats [txt x]
+
+
+dialog :: AFSig s opq
+dialog x y = (\_ -> Element "dialog" x y)
+
+dialog' :: Sig s opq
+dialog' = Element "dialog"
+
+dialog_ :: AFSig_ s opq
+dialog_ x = (\_ -> Element "dialog" dats x)
+
+dialog'_ :: Sig_ s opq
+dialog'_ x = Element "dialog" dats x
+
+dialog__ :: AFSig__ s opq
+dialog__ x = (\_ -> Element "dialog" dats [txt x])
+
+dialog'__ :: Sig__ s opq
+dialog'__ x = Element "dialog" dats [txt x]
+
+
+dir :: AFSig s opq
+dir x y = (\_ -> Element "dir" x y)
+
+dir' :: Sig s opq
+dir' = Element "dir"
+
+dir_ :: AFSig_ s opq
+dir_ x = (\_ -> Element "dir" dats x)
+
+dir'_ :: Sig_ s opq
+dir'_ x = Element "dir" dats x
+
+dir__ :: AFSig__ s opq
+dir__ x = (\_ -> Element "dir" dats [txt x])
+
+dir'__ :: Sig__ s opq
+dir'__ x = Element "dir" dats [txt x]
+
+
+div :: AFSig s opq
+div x y = (\_ -> Element "div" x y)
+
+div' :: Sig s opq
+div' = Element "div"
+
+div_ :: AFSig_ s opq
+div_ x = (\_ -> Element "div" dats x)
+
+div'_ :: Sig_ s opq
+div'_ x = Element "div" dats x
+
+div__ :: AFSig__ s opq
+div__ x = (\_ -> Element "div" dats [txt x])
+
+div'__ :: Sig__ s opq
+div'__ x = Element "div" dats [txt x]
+
+
+dl :: AFSig s opq
+dl x y = (\_ -> Element "dl" x y)
+
+dl' :: Sig s opq
+dl' = Element "dl"
+
+dl_ :: AFSig_ s opq
+dl_ x = (\_ -> Element "dl" dats x)
+
+dl'_ :: Sig_ s opq
+dl'_ x = Element "dl" dats x
+
+dl__ :: AFSig__ s opq
+dl__ x = (\_ -> Element "dl" dats [txt x])
+
+dl'__ :: Sig__ s opq
+dl'__ x = Element "dl" dats [txt x]
+
+
+dt :: AFSig s opq
+dt x y = (\_ -> Element "dt" x y)
+
+dt' :: Sig s opq
+dt' = Element "dt"
+
+dt_ :: AFSig_ s opq
+dt_ x = (\_ -> Element "dt" dats x)
+
+dt'_ :: Sig_ s opq
+dt'_ x = Element "dt" dats x
+
+dt__ :: AFSig__ s opq
+dt__ x = (\_ -> Element "dt" dats [txt x])
+
+dt'__ :: Sig__ s opq
+dt'__ x = Element "dt" dats [txt x]
+
+
+em :: AFSig s opq
+em x y = (\_ -> Element "em" x y)
+
+em' :: Sig s opq
+em' = Element "em"
+
+em_ :: AFSig_ s opq
+em_ x = (\_ -> Element "em" dats x)
+
+em'_ :: Sig_ s opq
+em'_ x = Element "em" dats x
+
+em__ :: AFSig__ s opq
+em__ x = (\_ -> Element "em" dats [txt x])
+
+em'__ :: Sig__ s opq
+em'__ x = Element "em" dats [txt x]
+
+
+embed :: AFSig s opq
+embed x y = (\_ -> Element "embed" x y)
+
+embed' :: Sig s opq
+embed' = Element "embed"
+
+embed_ :: AFSig_ s opq
+embed_ x = (\_ -> Element "embed" dats x)
+
+embed'_ :: Sig_ s opq
+embed'_ x = Element "embed" dats x
+
+embed__ :: AFSig__ s opq
+embed__ x = (\_ -> Element "embed" dats [txt x])
+
+embed'__ :: Sig__ s opq
+embed'__ x = Element "embed" dats [txt x]
+
+
+fieldset :: AFSig s opq
+fieldset x y = (\_ -> Element "fieldset" x y)
+
+fieldset' :: Sig s opq
+fieldset' = Element "fieldset"
+
+fieldset_ :: AFSig_ s opq
+fieldset_ x = (\_ -> Element "fieldset" dats x)
+
+fieldset'_ :: Sig_ s opq
+fieldset'_ x = Element "fieldset" dats x
+
+fieldset__ :: AFSig__ s opq
+fieldset__ x = (\_ -> Element "fieldset" dats [txt x])
+
+fieldset'__ :: Sig__ s opq
+fieldset'__ x = Element "fieldset" dats [txt x]
+
+
+figcaption :: AFSig s opq
+figcaption x y = (\_ -> Element "figcaption" x y)
+
+figcaption' :: Sig s opq
+figcaption' = Element "figcaption"
+
+figcaption_ :: AFSig_ s opq
+figcaption_ x = (\_ -> Element "figcaption" dats x)
+
+figcaption'_ :: Sig_ s opq
+figcaption'_ x = Element "figcaption" dats x
+
+figcaption__ :: AFSig__ s opq
+figcaption__ x = (\_ -> Element "figcaption" dats [txt x])
+
+figcaption'__ :: Sig__ s opq
+figcaption'__ x = Element "figcaption" dats [txt x]
+
+
+figure :: AFSig s opq
+figure x y = (\_ -> Element "figure" x y)
+
+figure' :: Sig s opq
+figure' = Element "figure"
+
+figure_ :: AFSig_ s opq
+figure_ x = (\_ -> Element "figure" dats x)
+
+figure'_ :: Sig_ s opq
+figure'_ x = Element "figure" dats x
+
+figure__ :: AFSig__ s opq
+figure__ x = (\_ -> Element "figure" dats [txt x])
+
+figure'__ :: Sig__ s opq
+figure'__ x = Element "figure" dats [txt x]
+
+
+font :: AFSig s opq
+font x y = (\_ -> Element "font" x y)
+
+font' :: Sig s opq
+font' = Element "font"
+
+font_ :: AFSig_ s opq
+font_ x = (\_ -> Element "font" dats x)
+
+font'_ :: Sig_ s opq
+font'_ x = Element "font" dats x
+
+font__ :: AFSig__ s opq
+font__ x = (\_ -> Element "font" dats [txt x])
+
+font'__ :: Sig__ s opq
+font'__ x = Element "font" dats [txt x]
+
+
+footer :: AFSig s opq
+footer x y = (\_ -> Element "footer" x y)
+
+footer' :: Sig s opq
+footer' = Element "footer"
+
+footer_ :: AFSig_ s opq
+footer_ x = (\_ -> Element "footer" dats x)
+
+footer'_ :: Sig_ s opq
+footer'_ x = Element "footer" dats x
+
+footer__ :: AFSig__ s opq
+footer__ x = (\_ -> Element "footer" dats [txt x])
+
+footer'__ :: Sig__ s opq
+footer'__ x = Element "footer" dats [txt x]
+
+
+form :: AFSig s opq
+form x y = (\_ -> Element "form" x y)
+
+form' :: Sig s opq
+form' = Element "form"
+
+form_ :: AFSig_ s opq
+form_ x = (\_ -> Element "form" dats x)
+
+form'_ :: Sig_ s opq
+form'_ x = Element "form" dats x
+
+form__ :: AFSig__ s opq
+form__ x = (\_ -> Element "form" dats [txt x])
+
+form'__ :: Sig__ s opq
+form'__ x = Element "form" dats [txt x]
+
+
+frame :: AFSig s opq
+frame x y = (\_ -> Element "frame" x y)
+
+frame' :: Sig s opq
+frame' = Element "frame"
+
+frame_ :: AFSig_ s opq
+frame_ x = (\_ -> Element "frame" dats x)
+
+frame'_ :: Sig_ s opq
+frame'_ x = Element "frame" dats x
+
+frame__ :: AFSig__ s opq
+frame__ x = (\_ -> Element "frame" dats [txt x])
+
+frame'__ :: Sig__ s opq
+frame'__ x = Element "frame" dats [txt x]
+
+
+frameset :: AFSig s opq
+frameset x y = (\_ -> Element "frameset" x y)
+
+frameset' :: Sig s opq
+frameset' = Element "frameset"
+
+frameset_ :: AFSig_ s opq
+frameset_ x = (\_ -> Element "frameset" dats x)
+
+frameset'_ :: Sig_ s opq
+frameset'_ x = Element "frameset" dats x
+
+frameset__ :: AFSig__ s opq
+frameset__ x = (\_ -> Element "frameset" dats [txt x])
+
+frameset'__ :: Sig__ s opq
+frameset'__ x = Element "frameset" dats [txt x]
+
+head :: AFSig s opq
+head x y = (\_ -> Element "head" x y)
+
+head' :: Sig s opq
+head' = Element "head"
+
+head_ :: AFSig_ s opq
+head_ x = (\_ -> Element "head" dats x)
+
+head'_ :: Sig_ s opq
+head'_ x = Element "head" dats x
+
+head__ :: AFSig__ s opq
+head__ x = (\_ -> Element "head" dats [txt x])
+
+head'__ :: Sig__ s opq
+head'__ x = Element "head" dats [txt x]
+
+
+header :: AFSig s opq
+header x y = (\_ -> Element "header" x y)
+
+header' :: Sig s opq
+header' = Element "header"
+
+header_ :: AFSig_ s opq
+header_ x = (\_ -> Element "header" dats x)
+
+header'_ :: Sig_ s opq
+header'_ x = Element "header" dats x
+
+header__ :: AFSig__ s opq
+header__ x = (\_ -> Element "header" dats [txt x])
+
+header'__ :: Sig__ s opq
+header'__ x = Element "header" dats [txt x]
+
+
+hr :: (s -> Node s opq)
+hr = (\_ -> Element "br" dats [])
+
+html :: AFSig s opq
+html x y = (\_ -> Element "html" x y)
+
+html' :: Sig s opq
+html' = Element "html"
+
+html_ :: AFSig_ s opq
+html_ x = (\_ -> Element "html" dats x)
+
+html'_ :: Sig_ s opq
+html'_ x = Element "html" dats x
+
+html__ :: AFSig__ s opq
+html__ x = (\_ -> Element "html" dats [txt x])
+
+html'__ :: Sig__ s opq
+html'__ x = Element "html" dats [txt x]
+
+
+i :: AFSig s opq
+i x y = (\_ -> Element "i" x y)
+
+i' :: Sig s opq
+i' = Element "i"
+
+i_ :: AFSig_ s opq
+i_ x = (\_ -> Element "i" dats x)
+
+i'_ :: Sig_ s opq
+i'_ x = Element "i" dats x
+
+i__ :: AFSig__ s opq
+i__ x = (\_ -> Element "i" dats [txt x])
+
+i'__ :: Sig__ s opq
+i'__ x = Element "i" dats [txt x]
+
+
+iframe :: AFSig s opq
+iframe x y = (\_ -> Element "iframe" x y)
+
+iframe' :: Sig s opq
+iframe' = Element "iframe"
+
+iframe_ :: AFSig_ s opq
+iframe_ x = (\_ -> Element "iframe" dats x)
+
+iframe'_ :: Sig_ s opq
+iframe'_ x = Element "iframe" dats x
+
+iframe__ :: AFSig__ s opq
+iframe__ x = (\_ -> Element "iframe" dats [txt x])
+
+iframe'__ :: Sig__ s opq
+iframe'__ x = Element "iframe" dats [txt x]
+
+
+img :: (s -> Attributes s opq) -> (s -> Node s opq)
+img x = (\_ -> Element "img" x [])
+
+img' :: (s -> Attributes s opq) -> Node s opq
+img' x = Element "img" x []
+
+img_ :: (s -> Node s opq)
+img_ = (\_ -> Element "img" dats [])
+
+img'_ :: Node s opq
+img'_ = Element "img" dats []
+
+input :: AFSig s opq
+input x y = (\_ -> Element "input" x y)
+
+input' :: Sig s opq
+input' = Element "input"
+
+input_ :: AFSig_ s opq
+input_ x = (\_ -> Element "input" dats x)
+
+input'_ :: Sig_ s opq
+input'_ x = Element "input" dats x
+
+input__ :: AFSig__ s opq
+input__ x = (\_ -> Element "input" dats [txt x])
+
+input'__ :: Sig__ s opq
+input'__ x = Element "input" dats [txt x]
+
+
+ins :: AFSig s opq
+ins x y = (\_ -> Element "ins" x y)
+
+ins' :: Sig s opq
+ins' = Element "ins"
+
+ins_ :: AFSig_ s opq
+ins_ x = (\_ -> Element "ins" dats x)
+
+ins'_ :: Sig_ s opq
+ins'_ x = Element "ins" dats x
+
+ins__ :: AFSig__ s opq
+ins__ x = (\_ -> Element "ins" dats [txt x])
+
+ins'__ :: Sig__ s opq
+ins'__ x = Element "ins" dats [txt x]
+
+
+kbd :: AFSig s opq
+kbd x y = (\_ -> Element "kbd" x y)
+
+kbd' :: Sig s opq
+kbd' = Element "kbd"
+
+kbd_ :: AFSig_ s opq
+kbd_ x = (\_ -> Element "kbd" dats x)
+
+kbd'_ :: Sig_ s opq
+kbd'_ x = Element "kbd" dats x
+
+kbd__ :: AFSig__ s opq
+kbd__ x = (\_ -> Element "kbd" dats [txt x])
+
+kbd'__ :: Sig__ s opq
+kbd'__ x = Element "kbd" dats [txt x]
+
+
+label :: AFSig s opq
+label x y = (\_ -> Element "label" x y)
+
+label' :: Sig s opq
+label' = Element "label"
+
+label_ :: AFSig_ s opq
+label_ x = (\_ -> Element "label" dats x)
+
+label'_ :: Sig_ s opq
+label'_ x = Element "label" dats x
+
+label__ :: AFSig__ s opq
+label__ x = (\_ -> Element "label" dats [txt x])
+
+label'__ :: Sig__ s opq
+label'__ x = Element "label" dats [txt x]
+
+
+legend :: AFSig s opq
+legend x y = (\_ -> Element "legend" x y)
+
+legend' :: Sig s opq
+legend' = Element "legend"
+
+legend_ :: AFSig_ s opq
+legend_ x = (\_ -> Element "legend" dats x)
+
+legend'_ :: Sig_ s opq
+legend'_ x = Element "legend" dats x
+
+legend__ :: AFSig__ s opq
+legend__ x = (\_ -> Element "legend" dats [txt x])
+
+legend'__ :: Sig__ s opq
+legend'__ x = Element "legend" dats [txt x]
+
+
+li :: AFSig s opq
+li x y = (\_ -> Element "li" x y)
+
+li' :: Sig s opq
+li' = Element "li"
+
+li_ :: AFSig_ s opq
+li_ x = (\_ -> Element "li" dats x)
+
+li'_ :: Sig_ s opq
+li'_ x = Element "li" dats x
+
+li__ :: AFSig__ s opq
+li__ x = (\_ -> Element "li" dats [txt x])
+
+li'__ :: Sig__ s opq
+li'__ x = Element "li" dats [txt x]
+
+
+link :: AFSig s opq
+link x y = (\_ -> Element "link" x y)
+
+link' :: Sig s opq
+link' = Element "link"
+
+link_ :: AFSig_ s opq
+link_ x = (\_ -> Element "link" dats x)
+
+link'_ :: Sig_ s opq
+link'_ x = Element "link" dats x
+
+link__ :: AFSig__ s opq
+link__ x = (\_ -> Element "link" dats [txt x])
+
+link'__ :: Sig__ s opq
+link'__ x = Element "link" dats [txt x]
+
+
+main :: AFSig s opq
+main x y = (\_ -> Element "main" x y)
+
+main' :: Sig s opq
+main' = Element "main"
+
+main_ :: AFSig_ s opq
+main_ x = (\_ -> Element "main" dats x)
+
+main'_ :: Sig_ s opq
+main'_ x = Element "main" dats x
+
+main__ :: AFSig__ s opq
+main__ x = (\_ -> Element "main" dats [txt x])
+
+main'__ :: Sig__ s opq
+main'__ x = Element "main" dats [txt x]
+
+
+map :: AFSig s opq
+map x y = (\_ -> Element "map" x y)
+
+map' :: Sig s opq
+map' = Element "map"
+
+map_ :: AFSig_ s opq
+map_ x = (\_ -> Element "map" dats x)
+
+map'_ :: Sig_ s opq
+map'_ x = Element "map" dats x
+
+map__ :: AFSig__ s opq
+map__ x = (\_ -> Element "map" dats [txt x])
+
+map'__ :: Sig__ s opq
+map'__ x = Element "map" dats [txt x]
+
+
+mark :: AFSig s opq
+mark x y = (\_ -> Element "mark" x y)
+
+mark' :: Sig s opq
+mark' = Element "mark"
+
+mark_ :: AFSig_ s opq
+mark_ x = (\_ -> Element "mark" dats x)
+
+mark'_ :: Sig_ s opq
+mark'_ x = Element "mark" dats x
+
+mark__ :: AFSig__ s opq
+mark__ x = (\_ -> Element "mark" dats [txt x])
+
+mark'__ :: Sig__ s opq
+mark'__ x = Element "mark" dats [txt x]
+
+
+meta :: AFSig s opq
+meta x y = (\_ -> Element "meta" x y)
+
+meta' :: Sig s opq
+meta' = Element "meta"
+
+meta_ :: AFSig_ s opq
+meta_ x = (\_ -> Element "meta" dats x)
+
+meta'_ :: Sig_ s opq
+meta'_ x = Element "meta" dats x
+
+meta__ :: AFSig__ s opq
+meta__ x = (\_ -> Element "meta" dats [txt x])
+
+meta'__ :: Sig__ s opq
+meta'__ x = Element "meta" dats [txt x]
+
+
+meter :: AFSig s opq
+meter x y = (\_ -> Element "meter" x y)
+
+meter' :: Sig s opq
+meter' = Element "meter"
+
+meter_ :: AFSig_ s opq
+meter_ x = (\_ -> Element "meter" dats x)
+
+meter'_ :: Sig_ s opq
+meter'_ x = Element "meter" dats x
+
+meter__ :: AFSig__ s opq
+meter__ x = (\_ -> Element "meter" dats [txt x])
+
+meter'__ :: Sig__ s opq
+meter'__ x = Element "meter" dats [txt x]
+
+
+nav :: AFSig s opq
+nav x y = (\_ -> Element "nav" x y)
+
+nav' :: Sig s opq
+nav' = Element "nav"
+
+nav_ :: AFSig_ s opq
+nav_ x = (\_ -> Element "nav" dats x)
+
+nav'_ :: Sig_ s opq
+nav'_ x = Element "nav" dats x
+
+nav__ :: AFSig__ s opq
+nav__ x = (\_ -> Element "nav" dats [txt x])
+
+nav'__ :: Sig__ s opq
+nav'__ x = Element "nav" dats [txt x]
+
+
+noframes :: AFSig s opq
+noframes x y = (\_ -> Element "noframes" x y)
+
+noframes' :: Sig s opq
+noframes' = Element "noframes"
+
+noframes_ :: AFSig_ s opq
+noframes_ x = (\_ -> Element "noframes" dats x)
+
+noframes'_ :: Sig_ s opq
+noframes'_ x = Element "noframes" dats x
+
+noframes__ :: AFSig__ s opq
+noframes__ x = (\_ -> Element "noframes" dats [txt x])
+
+noframes'__ :: Sig__ s opq
+noframes'__ x = Element "noframes" dats [txt x]
+
+
+noscript :: AFSig s opq
+noscript x y = (\_ -> Element "noscript" x y)
+
+noscript' :: Sig s opq
+noscript' = Element "noscript"
+
+noscript_ :: AFSig_ s opq
+noscript_ x = (\_ -> Element "noscript" dats x)
+
+noscript'_ :: Sig_ s opq
+noscript'_ x = Element "noscript" dats x
+
+noscript__ :: AFSig__ s opq
+noscript__ x = (\_ -> Element "noscript" dats [txt x])
+
+noscript'__ :: Sig__ s opq
+noscript'__ x = Element "noscript" dats [txt x]
+
+
+object :: AFSig s opq
+object x y = (\_ -> Element "object" x y)
+
+object' :: Sig s opq
+object' = Element "object"
+
+object_ :: AFSig_ s opq
+object_ x = (\_ -> Element "object" dats x)
+
+object'_ :: Sig_ s opq
+object'_ x = Element "object" dats x
+
+object__ :: AFSig__ s opq
+object__ x = (\_ -> Element "object" dats [txt x])
+
+object'__ :: Sig__ s opq
+object'__ x = Element "object" dats [txt x]
+
+
+ol :: AFSig s opq
+ol x y = (\_ -> Element "ol" x y)
+
+ol' :: Sig s opq
+ol' = Element "ol"
+
+ol_ :: AFSig_ s opq
+ol_ x = (\_ -> Element "ol" dats x)
+
+ol'_ :: Sig_ s opq
+ol'_ x = Element "ol" dats x
+
+ol__ :: AFSig__ s opq
+ol__ x = (\_ -> Element "ol" dats [txt x])
+
+ol'__ :: Sig__ s opq
+ol'__ x = Element "ol" dats [txt x]
+
+
+optgroup :: AFSig s opq
+optgroup x y = (\_ -> Element "optgroup" x y)
+
+optgroup' :: Sig s opq
+optgroup' = Element "optgroup"
+
+optgroup_ :: AFSig_ s opq
+optgroup_ x = (\_ -> Element "optgroup" dats x)
+
+optgroup'_ :: Sig_ s opq
+optgroup'_ x = Element "optgroup" dats x
+
+optgroup__ :: AFSig__ s opq
+optgroup__ x = (\_ -> Element "optgroup" dats [txt x])
+
+optgroup'__ :: Sig__ s opq
+optgroup'__ x = Element "optgroup" dats [txt x]
+
+
+option :: AFSig s opq
+option x y = (\_ -> Element "option" x y)
+
+option' :: Sig s opq
+option' = Element "option"
+
+option_ :: AFSig_ s opq
+option_ x = (\_ -> Element "option" dats x)
+
+option'_ :: Sig_ s opq
+option'_ x = Element "option" dats x
+
+option__ :: AFSig__ s opq
+option__ x = (\_ -> Element "option" dats [txt x])
+
+option'__ :: Sig__ s opq
+option'__ x = Element "option" dats [txt x]
+
+
+output :: AFSig s opq
+output x y = (\_ -> Element "output" x y)
+
+output' :: Sig s opq
+output' = Element "output"
+
+output_ :: AFSig_ s opq
+output_ x = (\_ -> Element "output" dats x)
+
+output'_ :: Sig_ s opq
+output'_ x = Element "output" dats x
+
+output__ :: AFSig__ s opq
+output__ x = (\_ -> Element "output" dats [txt x])
+
+output'__ :: Sig__ s opq
+output'__ x = Element "output" dats [txt x]
+
+
+p :: AFSig s opq
+p x y = (\_ -> Element "p" x y)
+
+p' :: Sig s opq
+p' = Element "p"
+
+p_ :: AFSig_ s opq
+p_ x = (\_ -> Element "p" dats x)
+
+p'_ :: Sig_ s opq
+p'_ x = Element "p" dats x
+
+p__ :: AFSig__ s opq
+p__ x = (\_ -> Element "p" dats [txt x])
+
+p'__ :: Sig__ s opq
+p'__ x = Element "p" dats [txt x]
+
+
+param :: AFSig s opq
+param x y = (\_ -> Element "param" x y)
+
+param' :: Sig s opq
+param' = Element "param"
+
+param_ :: AFSig_ s opq
+param_ x = (\_ -> Element "param" dats x)
+
+param'_ :: Sig_ s opq
+param'_ x = Element "param" dats x
+
+param__ :: AFSig__ s opq
+param__ x = (\_ -> Element "param" dats [txt x])
+
+param'__ :: Sig__ s opq
+param'__ x = Element "param" dats [txt x]
+
+
+picture :: AFSig s opq
+picture x y = (\_ -> Element "picture" x y)
+
+picture' :: Sig s opq
+picture' = Element "picture"
+
+picture_ :: AFSig_ s opq
+picture_ x = (\_ -> Element "picture" dats x)
+
+picture'_ :: Sig_ s opq
+picture'_ x = Element "picture" dats x
+
+picture__ :: AFSig__ s opq
+picture__ x = (\_ -> Element "picture" dats [txt x])
+
+picture'__ :: Sig__ s opq
+picture'__ x = Element "picture" dats [txt x]
+
+
+pre :: AFSig s opq
+pre x y = (\_ -> Element "pre" x y)
+
+pre' :: Sig s opq
+pre' = Element "pre"
+
+pre_ :: AFSig_ s opq
+pre_ x = (\_ -> Element "pre" dats x)
+
+pre'_ :: Sig_ s opq
+pre'_ x = Element "pre" dats x
+
+pre__ :: AFSig__ s opq
+pre__ x = (\_ -> Element "pre" dats [txt x])
+
+pre'__ :: Sig__ s opq
+pre'__ x = Element "pre" dats [txt x]
+
+
+progress :: AFSig s opq
+progress x y = (\_ -> Element "progress" x y)
+
+progress' :: Sig s opq
+progress' = Element "progress"
+
+progress_ :: AFSig_ s opq
+progress_ x = (\_ -> Element "progress" dats x)
+
+progress'_ :: Sig_ s opq
+progress'_ x = Element "progress" dats x
+
+progress__ :: AFSig__ s opq
+progress__ x = (\_ -> Element "progress" dats [txt x])
+
+progress'__ :: Sig__ s opq
+progress'__ x = Element "progress" dats [txt x]
+
+
+q :: AFSig s opq
+q x y = (\_ -> Element "q" x y)
+
+q' :: Sig s opq
+q' = Element "q"
+
+q_ :: AFSig_ s opq
+q_ x = (\_ -> Element "q" dats x)
+
+q'_ :: Sig_ s opq
+q'_ x = Element "q" dats x
+
+q__ :: AFSig__ s opq
+q__ x = (\_ -> Element "q" dats [txt x])
+
+q'__ :: Sig__ s opq
+q'__ x = Element "q" dats [txt x]
+
+
+rp :: AFSig s opq
+rp x y = (\_ -> Element "rp" x y)
+
+rp' :: Sig s opq
+rp' = Element "rp"
+
+rp_ :: AFSig_ s opq
+rp_ x = (\_ -> Element "rp" dats x)
+
+rp'_ :: Sig_ s opq
+rp'_ x = Element "rp" dats x
+
+rp__ :: AFSig__ s opq
+rp__ x = (\_ -> Element "rp" dats [txt x])
+
+rp'__ :: Sig__ s opq
+rp'__ x = Element "rp" dats [txt x]
+
+
+rt :: AFSig s opq
+rt x y = (\_ -> Element "rt" x y)
+
+rt' :: Sig s opq
+rt' = Element "rt"
+
+rt_ :: AFSig_ s opq
+rt_ x = (\_ -> Element "rt" dats x)
+
+rt'_ :: Sig_ s opq
+rt'_ x = Element "rt" dats x
+
+rt__ :: AFSig__ s opq
+rt__ x = (\_ -> Element "rt" dats [txt x])
+
+rt'__ :: Sig__ s opq
+rt'__ x = Element "rt" dats [txt x]
+
+
+ruby :: AFSig s opq
+ruby x y = (\_ -> Element "ruby" x y)
+
+ruby' :: Sig s opq
+ruby' = Element "ruby"
+
+ruby_ :: AFSig_ s opq
+ruby_ x = (\_ -> Element "ruby" dats x)
+
+ruby'_ :: Sig_ s opq
+ruby'_ x = Element "ruby" dats x
+
+ruby__ :: AFSig__ s opq
+ruby__ x = (\_ -> Element "ruby" dats [txt x])
+
+ruby'__ :: Sig__ s opq
+ruby'__ x = Element "ruby" dats [txt x]
+
+
+s :: AFSig s opq
+s x y = (\_ -> Element "s" x y)
+
+s' :: Sig s opq
+s' = Element "s"
+
+s_ :: AFSig_ s opq
+s_ x = (\_ -> Element "s" dats x)
+
+s'_ :: Sig_ s opq
+s'_ x = Element "s" dats x
+
+s__ :: AFSig__ s opq
+s__ x = (\_ -> Element "s" dats [txt x])
+
+s'__ :: Sig__ s opq
+s'__ x = Element "s" dats [txt x]
+
+
+samp :: AFSig s opq
+samp x y = (\_ -> Element "samp" x y)
+
+samp' :: Sig s opq
+samp' = Element "samp"
+
+samp_ :: AFSig_ s opq
+samp_ x = (\_ -> Element "samp" dats x)
+
+samp'_ :: Sig_ s opq
+samp'_ x = Element "samp" dats x
+
+samp__ :: AFSig__ s opq
+samp__ x = (\_ -> Element "samp" dats [txt x])
+
+samp'__ :: Sig__ s opq
+samp'__ x = Element "samp" dats [txt x]
+
+
+script :: AFSig s opq
+script x y = (\_ -> Element "script" x y)
+
+script' :: Sig s opq
+script' = Element "script"
+
+script_ :: AFSig_ s opq
+script_ x = (\_ -> Element "script" dats x)
+
+script'_ :: Sig_ s opq
+script'_ x = Element "script" dats x
+
+script__ :: AFSig__ s opq
+script__ x = (\_ -> Element "script" dats [txt x])
+
+script'__ :: Sig__ s opq
+script'__ x = Element "script" dats [txt x]
+
+
+section :: AFSig s opq
+section x y = (\_ -> Element "section" x y)
+
+section' :: Sig s opq
+section' = Element "section"
+
+section_ :: AFSig_ s opq
+section_ x = (\_ -> Element "section" dats x)
+
+section'_ :: Sig_ s opq
+section'_ x = Element "section" dats x
+
+section__ :: AFSig__ s opq
+section__ x = (\_ -> Element "section" dats [txt x])
+
+section'__ :: Sig__ s opq
+section'__ x = Element "section" dats [txt x]
+
+
+select :: AFSig s opq
+select x y = (\_ -> Element "select" x y)
+
+select' :: Sig s opq
+select' = Element "select"
+
+select_ :: AFSig_ s opq
+select_ x = (\_ -> Element "select" dats x)
+
+select'_ :: Sig_ s opq
+select'_ x = Element "select" dats x
+
+select__ :: AFSig__ s opq
+select__ x = (\_ -> Element "select" dats [txt x])
+
+select'__ :: Sig__ s opq
+select'__ x = Element "select" dats [txt x]
+
+
+small :: AFSig s opq
+small x y = (\_ -> Element "small" x y)
+
+small' :: Sig s opq
+small' = Element "small"
+
+small_ :: AFSig_ s opq
+small_ x = (\_ -> Element "small" dats x)
+
+small'_ :: Sig_ s opq
+small'_ x = Element "small" dats x
+
+small__ :: AFSig__ s opq
+small__ x = (\_ -> Element "small" dats [txt x])
+
+small'__ :: Sig__ s opq
+small'__ x = Element "small" dats [txt x]
+
+
+source :: AFSig s opq
+source x y = (\_ -> Element "source" x y)
+
+source' :: Sig s opq
+source' = Element "source"
+
+source_ :: AFSig_ s opq
+source_ x = (\_ -> Element "source" dats x)
+
+source'_ :: Sig_ s opq
+source'_ x = Element "source" dats x
+
+source__ :: AFSig__ s opq
+source__ x = (\_ -> Element "source" dats [txt x])
+
+source'__ :: Sig__ s opq
+source'__ x = Element "source" dats [txt x]
+
+
+span :: AFSig s opq
+span x y = (\_ -> Element "span" x y)
+
+span' :: Sig s opq
+span' = Element "span"
+
+span_ :: AFSig_ s opq
+span_ x = (\_ -> Element "span" dats x)
+
+span'_ :: Sig_ s opq
+span'_ x = Element "span" dats x
+
+span__ :: AFSig__ s opq
+span__ x = (\_ -> Element "span" dats [txt x])
+
+span'__ :: Sig__ s opq
+span'__ x = Element "span" dats [txt x]
+
+
+strike :: AFSig s opq
+strike x y = (\_ -> Element "strike" x y)
+
+strike' :: Sig s opq
+strike' = Element "strike"
+
+strike_ :: AFSig_ s opq
+strike_ x = (\_ -> Element "strike" dats x)
+
+strike'_ :: Sig_ s opq
+strike'_ x = Element "strike" dats x
+
+strike__ :: AFSig__ s opq
+strike__ x = (\_ -> Element "strike" dats [txt x])
+
+strike'__ :: Sig__ s opq
+strike'__ x = Element "strike" dats [txt x]
+
+
+strong :: AFSig s opq
+strong x y = (\_ -> Element "strong" x y)
+
+strong' :: Sig s opq
+strong' = Element "strong"
+
+strong_ :: AFSig_ s opq
+strong_ x = (\_ -> Element "strong" dats x)
+
+strong'_ :: Sig_ s opq
+strong'_ x = Element "strong" dats x
+
+strong__ :: AFSig__ s opq
+strong__ x = (\_ -> Element "strong" dats [txt x])
+
+strong'__ :: Sig__ s opq
+strong'__ x = Element "strong" dats [txt x]
+
+
+style :: AFSig s opq
+style x y = (\_ -> Element "style" x y)
+
+style' :: Sig s opq
+style' = Element "style"
+
+style_ :: AFSig_ s opq
+style_ x = (\_ -> Element "style" dats x)
+
+style'_ :: Sig_ s opq
+style'_ x = Element "style" dats x
+
+style__ :: AFSig__ s opq
+style__ x = (\_ -> Element "style" dats [txt x])
+
+style'__ :: Sig__ s opq
+style'__ x = Element "style" dats [txt x]
+
+
+sub :: AFSig s opq
+sub x y = (\_ -> Element "sub" x y)
+
+sub' :: Sig s opq
+sub' = Element "sub"
+
+sub_ :: AFSig_ s opq
+sub_ x = (\_ -> Element "sub" dats x)
+
+sub'_ :: Sig_ s opq
+sub'_ x = Element "sub" dats x
+
+sub__ :: AFSig__ s opq
+sub__ x = (\_ -> Element "sub" dats [txt x])
+
+sub'__ :: Sig__ s opq
+sub'__ x = Element "sub" dats [txt x]
+
+
+summary :: AFSig s opq
+summary x y = (\_ -> Element "summary" x y)
+
+summary' :: Sig s opq
+summary' = Element "summary"
+
+summary_ :: AFSig_ s opq
+summary_ x = (\_ -> Element "summary" dats x)
+
+summary'_ :: Sig_ s opq
+summary'_ x = Element "summary" dats x
+
+summary__ :: AFSig__ s opq
+summary__ x = (\_ -> Element "summary" dats [txt x])
+
+summary'__ :: Sig__ s opq
+summary'__ x = Element "summary" dats [txt x]
+
+
+sup :: AFSig s opq
+sup x y = (\_ -> Element "sup" x y)
+
+sup' :: Sig s opq
+sup' = Element "sup"
+
+sup_ :: AFSig_ s opq
+sup_ x = (\_ -> Element "sup" dats x)
+
+sup'_ :: Sig_ s opq
+sup'_ x = Element "sup" dats x
+
+sup__ :: AFSig__ s opq
+sup__ x = (\_ -> Element "sup" dats [txt x])
+
+sup'__ :: Sig__ s opq
+sup'__ x = Element "sup" dats [txt x]
+
+
+svg :: AFSig s opq
+svg x y = (\_ -> Element "svg" x y)
+
+svg' :: Sig s opq
+svg' = Element "svg"
+
+svg_ :: AFSig_ s opq
+svg_ x = (\_ -> Element "svg" dats x)
+
+svg'_ :: Sig_ s opq
+svg'_ x = Element "svg" dats x
+
+svg__ :: AFSig__ s opq
+svg__ x = (\_ -> Element "svg" dats [txt x])
+
+svg'__ :: Sig__ s opq
+svg'__ x = Element "svg" dats [txt x]
+
+
+table :: AFSig s opq
+table x y = (\_ -> Element "table" x y)
+
+table' :: Sig s opq
+table' = Element "table"
+
+table_ :: AFSig_ s opq
+table_ x = (\_ -> Element "table" dats x)
+
+table'_ :: Sig_ s opq
+table'_ x = Element "table" dats x
+
+table__ :: AFSig__ s opq
+table__ x = (\_ -> Element "table" dats [txt x])
+
+table'__ :: Sig__ s opq
+table'__ x = Element "table" dats [txt x]
+
+
+tbody :: AFSig s opq
+tbody x y = (\_ -> Element "tbody" x y)
+
+tbody' :: Sig s opq
+tbody' = Element "tbody"
+
+tbody_ :: AFSig_ s opq
+tbody_ x = (\_ -> Element "tbody" dats x)
+
+tbody'_ :: Sig_ s opq
+tbody'_ x = Element "tbody" dats x
+
+tbody__ :: AFSig__ s opq
+tbody__ x = (\_ -> Element "tbody" dats [txt x])
+
+tbody'__ :: Sig__ s opq
+tbody'__ x = Element "tbody" dats [txt x]
+
+
+td :: AFSig s opq
+td x y = (\_ -> Element "td" x y)
+
+td' :: Sig s opq
+td' = Element "td"
+
+td_ :: AFSig_ s opq
+td_ x = (\_ -> Element "td" dats x)
+
+td'_ :: Sig_ s opq
+td'_ x = Element "td" dats x
+
+td__ :: AFSig__ s opq
+td__ x = (\_ -> Element "td" dats [txt x])
+
+td'__ :: Sig__ s opq
+td'__ x = Element "td" dats [txt x]
+
+
+template :: AFSig s opq
+template x y = (\_ -> Element "template" x y)
+
+template' :: Sig s opq
+template' = Element "template"
+
+template_ :: AFSig_ s opq
+template_ x = (\_ -> Element "template" dats x)
+
+template'_ :: Sig_ s opq
+template'_ x = Element "template" dats x
+
+template__ :: AFSig__ s opq
+template__ x = (\_ -> Element "template" dats [txt x])
+
+template'__ :: Sig__ s opq
+template'__ x = Element "template" dats [txt x]
+
+
+textarea :: AFSig s opq
+textarea x y = (\_ -> Element "textarea" x y)
+
+textarea' :: Sig s opq
+textarea' = Element "textarea"
+
+textarea_ :: AFSig_ s opq
+textarea_ x = (\_ -> Element "textarea" dats x)
+
+textarea'_ :: Sig_ s opq
+textarea'_ x = Element "textarea" dats x
+
+textarea__ :: AFSig__ s opq
+textarea__ x = (\_ -> Element "textarea" dats [txt x])
+
+textarea'__ :: Sig__ s opq
+textarea'__ x = Element "textarea" dats [txt x]
+
+
+tfoot :: AFSig s opq
+tfoot x y = (\_ -> Element "tfoot" x y)
+
+tfoot' :: Sig s opq
+tfoot' = Element "tfoot"
+
+tfoot_ :: AFSig_ s opq
+tfoot_ x = (\_ -> Element "tfoot" dats x)
+
+tfoot'_ :: Sig_ s opq
+tfoot'_ x = Element "tfoot" dats x
+
+tfoot__ :: AFSig__ s opq
+tfoot__ x = (\_ -> Element "tfoot" dats [txt x])
+
+tfoot'__ :: Sig__ s opq
+tfoot'__ x = Element "tfoot" dats [txt x]
+
+
+th :: AFSig s opq
+th x y = (\_ -> Element "th" x y)
+
+th' :: Sig s opq
+th' = Element "th"
+
+th_ :: AFSig_ s opq
+th_ x = (\_ -> Element "th" dats x)
+
+th'_ :: Sig_ s opq
+th'_ x = Element "th" dats x
+
+th__ :: AFSig__ s opq
+th__ x = (\_ -> Element "th" dats [txt x])
+
+th'__ :: Sig__ s opq
+th'__ x = Element "th" dats [txt x]
+
+
+thead :: AFSig s opq
+thead x y = (\_ -> Element "thead" x y)
+
+thead' :: Sig s opq
+thead' = Element "thead"
+
+thead_ :: AFSig_ s opq
+thead_ x = (\_ -> Element "thead" dats x)
+
+thead'_ :: Sig_ s opq
+thead'_ x = Element "thead" dats x
+
+thead__ :: AFSig__ s opq
+thead__ x = (\_ -> Element "thead" dats [txt x])
+
+thead'__ :: Sig__ s opq
+thead'__ x = Element "thead" dats [txt x]
+
+
+time :: AFSig s opq
+time x y = (\_ -> Element "time" x y)
+
+time' :: Sig s opq
+time' = Element "time"
+
+time_ :: AFSig_ s opq
+time_ x = (\_ -> Element "time" dats x)
+
+time'_ :: Sig_ s opq
+time'_ x = Element "time" dats x
+
+time__ :: AFSig__ s opq
+time__ x = (\_ -> Element "time" dats [txt x])
+
+time'__ :: Sig__ s opq
+time'__ x = Element "time" dats [txt x]
+
+
+title :: AFSig s opq
+title x y = (\_ -> Element "title" x y)
+
+title' :: Sig s opq
+title' = Element "title"
+
+title_ :: AFSig_ s opq
+title_ x = (\_ -> Element "title" dats x)
+
+title'_ :: Sig_ s opq
+title'_ x = Element "title" dats x
+
+title__ :: AFSig__ s opq
+title__ x = (\_ -> Element "title" dats [txt x])
+
+title'__ :: Sig__ s opq
+title'__ x = Element "title" dats [txt x]
+
+
+tr :: AFSig s opq
+tr x y = (\_ -> Element "tr" x y)
+
+tr' :: Sig s opq
+tr' = Element "tr"
+
+tr_ :: AFSig_ s opq
+tr_ x = (\_ -> Element "tr" dats x)
+
+tr'_ :: Sig_ s opq
+tr'_ x = Element "tr" dats x
+
+tr__ :: AFSig__ s opq
+tr__ x = (\_ -> Element "tr" dats [txt x])
+
+tr'__ :: Sig__ s opq
+tr'__ x = Element "tr" dats [txt x]
+
+
+track :: AFSig s opq
+track x y = (\_ -> Element "track" x y)
+
+track' :: Sig s opq
+track' = Element "track"
+
+track_ :: AFSig_ s opq
+track_ x = (\_ -> Element "track" dats x)
+
+track'_ :: Sig_ s opq
+track'_ x = Element "track" dats x
+
+track__ :: AFSig__ s opq
+track__ x = (\_ -> Element "track" dats [txt x])
+
+track'__ :: Sig__ s opq
+track'__ x = Element "track" dats [txt x]
+
+
+tt :: AFSig s opq
+tt x y = (\_ -> Element "tt" x y)
+
+tt' :: Sig s opq
+tt' = Element "tt"
+
+tt_ :: AFSig_ s opq
+tt_ x = (\_ -> Element "tt" dats x)
+
+tt'_ :: Sig_ s opq
+tt'_ x = Element "tt" dats x
+
+tt__ :: AFSig__ s opq
+tt__ x = (\_ -> Element "tt" dats [txt x])
+
+tt'__ :: Sig__ s opq
+tt'__ x = Element "tt" dats [txt x]
+
+
+u :: AFSig s opq
+u x y = (\_ -> Element "u" x y)
+
+u' :: Sig s opq
+u' = Element "u"
+
+u_ :: AFSig_ s opq
+u_ x = (\_ -> Element "u" dats x)
+
+u'_ :: Sig_ s opq
+u'_ x = Element "u" dats x
+
+u__ :: AFSig__ s opq
+u__ x = (\_ -> Element "u" dats [txt x])
+
+u'__ :: Sig__ s opq
+u'__ x = Element "u" dats [txt x]
+
+
+ul :: AFSig s opq
+ul x y = (\_ -> Element "ul" x y)
+
+ul' :: Sig s opq
+ul' = Element "ul"
+
+ul_ :: AFSig_ s opq
+ul_ x = (\_ -> Element "ul" dats x)
+
+ul'_ :: Sig_ s opq
+ul'_ x = Element "ul" dats x
+
+ul__ :: AFSig__ s opq
+ul__ x = (\_ -> Element "ul" dats [txt x])
+
+ul'__ :: Sig__ s opq
+ul'__ x = Element "ul" dats [txt x]
+
+
+var :: AFSig s opq
+var x y = (\_ -> Element "var" x y)
+
+var' :: Sig s opq
+var' = Element "var"
+
+var_ :: AFSig_ s opq
+var_ x = (\_ -> Element "var" dats x)
+
+var'_ :: Sig_ s opq
+var'_ x = Element "var" dats x
+
+var__ :: AFSig__ s opq
+var__ x = (\_ -> Element "var" dats [txt x])
+
+var'__ :: Sig__ s opq
+var'__ x = Element "var" dats [txt x]
+
+
+video :: AFSig s opq
+video x y = (\_ -> Element "video" x y)
+
+video' :: Sig s opq
+video' = Element "video"
+
+video_ :: AFSig_ s opq
+video_ x = (\_ -> Element "video" dats x)
+
+video'_ :: Sig_ s opq
+video'_ x = Element "video" dats x
+
+video__ :: AFSig__ s opq
+video__ x = (\_ -> Element "video" dats [txt x])
+
+video'__ :: Sig__ s opq
+video'__ x = Element "video" dats [txt x]
+
+
+wbr :: (s -> Node s opq)
+wbr = (\_ -> Element "br" dats [])
+
+txt :: String -> (s -> Node s opq)
+txt t = (\_ -> TextNode t)
+
+txt' :: String -> Node s opq
+txt' = TextNode
+
+
+h1 :: AFSig s opq
+h1 x y = (\_ -> Element "h1" x y)
+
+h1' :: Sig s opq
+h1' = Element "h1"
+
+h1_ :: AFSig_ s opq
+h1_ x = (\_ -> Element "h1" dats x)
+
+h1'_ :: Sig_ s opq
+h1'_ x = Element "h1" dats x
+
+h1__ :: AFSig__ s opq
+h1__ x = (\_ -> Element "h1" dats [txt x])
+
+h1'__ :: Sig__ s opq
+h1'__ x = Element "h1" dats [txt x]
+
+
+h2 :: AFSig s opq
+h2 x y = (\_ -> Element "h2" x y)
+
+h2' :: Sig s opq
+h2' = Element "h2"
+
+h2_ :: AFSig_ s opq
+h2_ x = (\_ -> Element "h2" dats x)
+
+h2'_ :: Sig_ s opq
+h2'_ x = Element "h2" dats x
+
+h2__ :: AFSig__ s opq
+h2__ x = (\_ -> Element "h2" dats [txt x])
+
+h2'__ :: Sig__ s opq
+h2'__ x = Element "h2" dats [txt x]
+
+
+h3 :: AFSig s opq
+h3 x y = (\_ -> Element "h3" x y)
+
+h3' :: Sig s opq
+h3' = Element "h3"
+
+h3_ :: AFSig_ s opq
+h3_ x = (\_ -> Element "h3" dats x)
+
+h3'_ :: Sig_ s opq
+h3'_ x = Element "h3" dats x
+
+h3__ :: AFSig__ s opq
+h3__ x = (\_ -> Element "h3" dats [txt x])
+
+h3'__ :: Sig__ s opq
+h3'__ x = Element "h3" dats [txt x]
+
+
+h4 :: AFSig s opq
+h4 x y = (\_ -> Element "h4" x y)
+
+h4' :: Sig s opq
+h4' = Element "h4"
+
+h4_ :: AFSig_ s opq
+h4_ x = (\_ -> Element "h4" dats x)
+
+h4'_ :: Sig_ s opq
+h4'_ x = Element "h4" dats x
+
+h4__ :: AFSig__ s opq
+h4__ x = (\_ -> Element "h4" dats [txt x])
+
+h4'__ :: Sig__ s opq
+h4'__ x = Element "h4" dats [txt x]
+
+
+h5 :: AFSig s opq
+h5 x y = (\_ -> Element "h5" x y)
+
+h5' :: Sig s opq
+h5' = Element "h5"
+
+h5_ :: AFSig_ s opq
+h5_ x = (\_ -> Element "h5" dats x)
+
+h5'_ :: Sig_ s opq
+h5'_ x = Element "h5" dats x
+
+h5__ :: AFSig__ s opq
+h5__ x = (\_ -> Element "h5" dats [txt x])
+
+h5'__ :: Sig__ s opq
+h5'__ x = Element "h5" dats [txt x]
+
+
+h6 :: AFSig s opq
+h6 x y = (\_ -> Element "h6" x y)
+
+h6' :: Sig s opq
+h6' = Element "h6"
+
+h6_ :: AFSig_ s opq
+h6_ x = (\_ -> Element "h6" dats x)
+
+h6'_ :: Sig_ s opq
+h6'_ x = Element "h6" dats x
+
+h6__ :: AFSig__ s opq
+h6__ x = (\_ -> Element "h6" dats [txt x])
+
+h6'__ :: Sig__ s opq
+h6'__ x = Element "h6" dats [txt x]
+ test/Spec.hs view
@@ -0,0 +1,102 @@+import           Control.Monad
+import           Control.Monad.Reader
+import           Data.IORef
+import           Prelude                 hiding ( div )
+import           Test.Hspec
+import           Web.Framework.Plzwrk
+import           Web.Framework.Plzwrk.MockJSVal
+import           Data.HashMap.Strict
+import           Web.Framework.Plzwrk.Tag(p_, txt, button, div'_)
+
+data MyState = MyState
+  { _name :: String
+  , _ctr  :: Int
+  }
+
+main :: IO ()
+main = hspec $ do
+  describe "Element with basic state" $ do
+    let domF =
+          (\x y -> div'_
+              [ p_ (take y $ repeat (txt (concat [x, show y])))
+              , button
+                (pure dats'
+                  { _simple   = singleton "id" "incr"
+                  , _handlers = singleton "click"
+                                          (\_ s -> pure $ s { _ctr = y + 1 })
+                  }
+                )
+                [txt "Increase counter"]
+              , button
+                (pure dats'
+                  { _simple   = singleton "id" "decr"
+                  , _handlers = singleton "click"
+                                          (\_ s -> pure $ s { _ctr = y - 1 })
+                  }
+                )
+                [txt "Decrease counter"]
+              ]
+            )
+            <$> _name
+            <*> _ctr
+    let state = MyState "Mike" 0
+    it "Creates the correct DOM from the state" $ do
+      rf          <- defaultInternalBrowser
+      mock        <- makeMockBrowserWithContext rf
+      refToOldDom <- newIORef (OldStuff state Nothing)
+      parentNode  <- getBody mock
+      newDom      <- runReaderT
+        (reconcile refToOldDom
+                   domF
+                   parentNode
+                   parentNode
+                   Nothing
+                   (Just $ hydrate state domF)
+        )
+        mock
+      writeIORef refToOldDom (OldStuff state newDom)
+      childrenLevel0 <- (getChildren mock) parentNode
+      length childrenLevel0 `shouldBe` 1
+      divtag <- (getTag mock) (head childrenLevel0)
+      divtag `shouldBe` "div"
+      childrenLevel1 <- (getChildren mock) (head childrenLevel0)
+      length childrenLevel1 `shouldBe` 3
+      ptag <- (getTag mock) (head childrenLevel1)
+      ptag `shouldBe` "p"
+      childrenLevel2 <- (getChildren mock) (head childrenLevel1)
+      length childrenLevel2 `shouldBe` 0
+      -- increment 4 times
+      (getElementById mock) "incr"
+        >>= maybe (error "Incr node does not exist") (click mock)
+      (getElementById mock) "incr"
+        >>= maybe (error "Incr node does not exist") (click mock)
+      (getElementById mock) "incr"
+        >>= maybe (error "Incr node does not exist") (click mock)
+      (getElementById mock) "incr"
+        >>= maybe (error "Incr node does not exist") (click mock)
+      parentNode'     <- getBody mock
+      childrenLevel0' <- (getChildren mock) parentNode'
+      length childrenLevel0' `shouldBe` 1
+      divtag' <- (getTag mock) (head childrenLevel0')
+      divtag' `shouldBe` "div"
+      childrenLevel1' <- (getChildren mock) (head childrenLevel0')
+      length childrenLevel1' `shouldBe` 3
+      childrenLevel2' <- (getChildren mock) (head childrenLevel1')
+      length childrenLevel2' `shouldBe` 4
+      content' <- mapM (textContent mock) childrenLevel2'
+      content' `shouldBe` (take 4 $ repeat "Mike4")
+      (getElementById mock) "decr"
+        >>= maybe (error "Incr node does not exist") (click mock)
+      (getElementById mock) "decr"
+        >>= maybe (error "Incr node does not exist") (click mock)
+      parentNode''     <- getBody mock
+      childrenLevel0'' <- (getChildren mock) parentNode''
+      length childrenLevel0'' `shouldBe` 1
+      divtag'' <- (getTag mock) (head childrenLevel0'')
+      divtag'' `shouldBe` "div"
+      childrenLevel1'' <- (getChildren mock) (head childrenLevel0'')
+      length childrenLevel1'' `shouldBe` 3
+      childrenLevel2'' <- (getChildren mock) (head childrenLevel1'')
+      length childrenLevel2'' `shouldBe` 2
+      content'' <- mapM (textContent mock) childrenLevel2''
+      content'' `shouldBe` (take 2 $ repeat "Mike2")