packages feed

Shpadoinkle-backend-snabbdom 0.3.0.1 → 0.3.0.2

raw patch · 5 files changed

+259/−143 lines, 5 filesdep +containers

Dependencies added: containers

Files

− CHANGELOG.md
README.md view
@@ -1,6 +1,6 @@ # Shpadoinkle Backend Snabbdom -[![Goldwater](https://gitlab.com/fresheyeball/Shpadoinkle/badges/master/pipeline.svg)](https://gitlab.com/fresheyeball/Shpadoinkle)+[![Goldwater](https://gitlab.com/platonic/shpadoinkle/badges/master/pipeline.svg)](https://gitlab.com/platonic/shpadoinkle) [![Haddock](https://img.shields.io/badge/haddock-master-informational)](https://shpadoinkle.org/backend-snabbdom) [![BSD-3](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) [![built with nix](https://img.shields.io/badge/built%20with-nix-41439a)](https://builtwithnix.org)@@ -12,7 +12,23 @@  > Snabbdom consists of an extremely simple, performant, and extensible core that is only ≈ 200 SLOC. It offers a modular architecture with rich functionality for extensions through custom modules. To keep the core simple, all non-essential functionality is delegated to modules. -These design decisions made Snabbdom a good fit for Shpadoinkle's first high-performance pure JavaScript backend. Right now Snabbdom is being provided using [CloudFlare](https://cdnjs.com/) content delivery network (CDN) and is not included in this repo. This is great for getting started fast and having a transparent developer experience where you can simply switch to the backend of your choosing. However, this is not a stable long term approach as the CDN artifact could be removed at any time. If you wish to use Snabbdom in production, I recommend either:+These design decisions made Snabbdom a good fit for Shpadoinkle's first high-performance pure JavaScript backend. Right now Snabbdom is being provided statically, and a [slightly modified build](https://github.com/fresheyeball/snabbdom) is included in this repo. Although this increases the size of the resulting executable, it's necessary for reproducible and stable builds. -- Proactively monitoring the CDN endpoints-- Wrap `SnabbdomT` in your own `newtype` and overriding the `setup` method in the `Backend` instance with a mechanism where you provide Snabbdom's JavaScript artifacts yourself.+# Building++In order to re-build `Shpadoinkle/Backend/Snabbdom/Setup.js`, it needs to be bundled with a tool like [parcel](https://parceljs.org/) - the following methodology is how it's currently done:++```bash+# clone outside the source directory of Shpadoinkl+git clone git@github.com:snabbdom/snabbdom.git+# compile its typescript so we can bundle the javascript+cd snabbdom && npm install && npm run compile+# Setup_src.js imports the snabbdom sources locally, so we need to manually move it+cp path-to-shpadoinkle/backends/snabbdom/Shpadoinkle/Backend/Snabbdom/Setup_src.js build/package/+# nix is most reliable for running parcel+nix-shell -p nodePackages.parcel-bundler --command "parcel build build/package/Setup_src.js"+# copy the bundled output as Setup.js+cp dist/Setup_src.js path-to-shpadoinkle/backends/snabbdom/Shpadoinkle/Backend/Snabbdom/Setup.js+```++Now when you build your shpadoinkle project, this new `Setup.js` will be statically allocated with your GHCJS output.
Shpadoinkle-backend-snabbdom.cabal view
@@ -1,41 +1,48 @@-cabal-version: 1.12---- This file has been generated from package.yaml by hpack version 0.33.0.------ see: https://github.com/sol/hpack------ hash: 69cf96a52080c262156727e824b26eaebddc6ac0713edcc0f367f821161c934b--name:           Shpadoinkle-backend-snabbdom-version:        0.3.0.1-synopsis:       Use the high-performance Snabbdom virtual dom library written in JavaScript.-description:    Snabbdom is a battle-tested virtual DOM library for JavaScript. It's extremely fast, lean, and modular. Snabbdom's design makes Snabbdom a natural choice for a Shpadoinkle rendering backend, as it has a similar core philosophy of "just don't do much" and is friendly to purely functional binding.-category:       Web-author:         Isaac Shapira-maintainer:     fresheyeball@protonmail.com-license:        BSD3-license-file:   LICENSE-build-type:     Simple+cabal-version: 2.2+name:          Shpadoinkle-backend-snabbdom+version:       0.3.0.2+category:      Web+author:        Isaac Shapira+maintainer:    isaac.shapira@platonic.systems+license:       BSD-3-Clause+license-file:  LICENSE+build-type:    Simple extra-source-files:-    README.md-    CHANGELOG.md-    Shpadoinkle/Backend/Snabbdom/Setup.js+  README.md+  Shpadoinkle/Backend/Snabbdom/Setup.js+synopsis:+  Use the high-performance Snabbdom virtual dom library written in JavaScript.+description:+  Snabbdom is a battle-tested virtual DOM library for JavaScript. It's extremely+  fast, lean, and modular. Snabbdom's design makes Snabbdom a natural choice for a+  Shpadoinkle rendering backend, as it has a similar core philosophy of+  "just don't do much" and is friendly to purely functional binding. + source-repository head   type: git-  location: https://gitlab.com/fresheyeball/Shpadoinkle.git+  location: https://gitlab.com/platonic/shpadoinkle.git + library   exposed-modules:-      Shpadoinkle.Backend.Snabbdom-  other-modules:-      Paths_Shpadoinkle_backend_snabbdom-  hs-source-dirs:-      ./.-  ghc-options: -Wall -Wcompat -fwarn-redundant-constraints -fwarn-incomplete-uni-patterns -fwarn-tabs -fwarn-incomplete-record-updates -fwarn-identities+    Shpadoinkle.Backend.Snabbdom++  hs-source-dirs: .++  ghc-options:+    -Wall+    -Wcompat+    -fwarn-redundant-constraints+    -fwarn-incomplete-uni-patterns+    -fwarn-tabs+    -fwarn-incomplete-record-updates+    -fwarn-identities+   build-depends:       Shpadoinkle     , base >=4.12.0 && <4.16+    , containers     , exceptions     , file-embed >=0.0.11 && <0.1     , ghcjs-dom >=0.9.4 && <0.20@@ -45,4 +52,5 @@     , text >=1.2.3 && <1.3     , transformers-base     , unliftio >=0.2.12 && <0.3+   default-language: Haskell2010
Shpadoinkle/Backend/Snabbdom.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE BangPatterns               #-} {-# LANGUAGE CPP                        #-} {-# LANGUAGE ExtendedDefaultRules       #-} {-# LANGUAGE FlexibleInstances          #-}@@ -7,6 +8,7 @@ {-# LANGUAGE MultiParamTypeClasses      #-} {-# LANGUAGE OverloadedStrings          #-} {-# LANGUAGE RankNTypes                 #-}+{-# LANGUAGE ScopedTypeVariables        #-} {-# LANGUAGE StandaloneDeriving         #-} {-# LANGUAGE TemplateHaskell            #-} {-# LANGUAGE TupleSections              #-}@@ -30,31 +32,51 @@   import           Control.Category            ((.))+#ifdef ghcjs_HOST_OS+import           Control.Monad               (join)+#endif import           Control.Monad.Base          (MonadBase (..), liftBaseDefault)-import           Control.Monad.Catch         (MonadCatch, MonadThrow)+import           Control.Monad.Catch         (MonadCatch, MonadMask, MonadThrow)+import           Control.Monad.Cont          (MonadCont)+import           Control.Monad.Except        (MonadError) import           Control.Monad.Reader        (MonadIO, MonadReader (..),                                               MonadTrans, ReaderT (..), forM_,-                                              void, (>=>))+                                              void)+import           Control.Monad.State         (MonadState) import           Control.Monad.Trans.Control (ComposeSt, MonadBaseControl (..),                                               MonadTransControl,                                               defaultLiftBaseWith,                                               defaultRestoreM)+import           Control.Monad.Writer        (MonadWriter) import           Data.FileEmbed              (embedStringFile)-import           Data.Text                   (Text, split)-import           Data.Traversable            (for)+import           Data.Map.Internal           (Map (Bin, Tip))+import           Data.Text                   (Text, isPrefixOf, words) import           GHCJS.DOM                   (currentDocumentUnchecked) import           GHCJS.DOM.Document          (createElement, getBodyUnsafe)-import           GHCJS.DOM.Element           (setAttribute)+import           GHCJS.DOM.Element           (setAttribute, setInnerHTML) import           GHCJS.DOM.Node              (appendChild)-import           Language.Javascript.JSaddle hiding (JSM, MonadJSM, liftJSM,-                                              (#))-import           Prelude                     hiding (id, (.))+#ifndef ghcjs_HOST_OS+import           Language.Javascript.JSaddle (FromJSVal (..), JSVal, Object,+                                              ToJSVal (..), create, eval, fun,+                                              function, jsTrue, jsg1, jsg2,+                                              jsg3, toJSBool, toJSString,+                                              unsafeGetProp, unsafeSetProp,+                                              valMakeText, valToObject)+#else+import           Language.Javascript.JSaddle (FromJSVal (..), JSVal, Object,+                                              ToJSVal (..), create, eval, fun,+                                              function, jsTrue, toJSBool,+                                              toJSString, unsafeGetProp,+                                              unsafeSetProp, valMakeText,+                                              valToObject)+#endif+import           Prelude                     hiding (id, words, (.)) import           UnliftIO                    (MonadUnliftIO (..), TVar,                                               UnliftIO (UnliftIO, unliftIO),                                               withUnliftIO) import           UnliftIO.Concurrent         (forkIO) -import           Shpadoinkle                 hiding (children, name, props)+import           Shpadoinkle   default (Text)@@ -71,14 +93,22 @@   , Applicative   , Monad   , MonadIO-  , MonadReader (TVar model)   , MonadTrans   , MonadTransControl   , MonadThrow   , MonadCatch+  , MonadMask+  , MonadWriter w+  , MonadState s+  , MonadError e+  , MonadCont   )  +snabbAsk :: Monad m => SnabbdomT model m (TVar model)+snabbAsk = Snabbdom ask++ #ifndef ghcjs_HOST_OS deriving instance MonadJSM m => MonadJSM (SnabbdomT model m) #endif@@ -88,6 +118,11 @@   liftBase = liftBaseDefault  +instance MonadReader r m => MonadReader r (SnabbdomT a m) where+  ask = Snabbdom . ReaderT $ const ask+  local f (Snabbdom rs) = Snabbdom $ ReaderT $ local f . runReaderT rs++ instance MonadBaseControl n m => MonadBaseControl n (SnabbdomT model m) where   type StM (SnabbdomT model m) a = ComposeSt (SnabbdomT model) m a   liftBaseWith = defaultLiftBaseWith@@ -111,54 +146,79 @@ runSnabbdom t (Snabbdom r) = runReaderT r t  -props :: Monad m => (m ~> JSM) -> TVar a -> [(Text, Prop (SnabbdomT a m) a)] -> JSM Object-props toJSM i xs = do+traverseWithKey_ :: Applicative t => (k -> a -> t ()) -> Map k a -> t ()+traverseWithKey_ f = go+  where+    go Tip             = pure ()+    go (Bin 1 k v _ _) = f k v+    go (Bin _ k v l r) = go l *> f k v *> go r+{-# INLINE traverseWithKey_ #-}+{-# SPECIALIZE traverseWithKey_ :: (k -> a -> JSM ()) -> Map k a -> JSM () #-}+++insertHook :: Text -> JSVal -> Object -> JSM ()+#ifndef ghcjs_HOST_OS+insertHook t f' hooksObj = void $ jsg3 "insertHook" t f' hooksObj+#else+insertHook t f' hooksObj = join $ insertHook' <$> toJSVal t <*> pure f' <*> toJSVal hooksObj+foreign import javascript unsafe "window['insertHook']($1,$2,$3)" insertHook' :: JSVal -> JSVal -> JSVal -> JSM ()+#endif+++{-# SPECIALIZE props :: NFData a => (JSM ~> JSM) -> TVar a -> Props (SnabbdomT a JSM) a -> JSM Object #-}+props :: Monad m => NFData a => (m ~> JSM) -> TVar a -> Props (SnabbdomT a m) a -> JSM Object+props toJSM i (Props xs) = do   o <- create   propsObj     <- create   listenersObj <- create   classesObj   <- create   attrsObj     <- create   hooksObj     <- create-  void $ xs `for` \(k, p) -> case p of-    PData d -> unsafeSetProp (toJSString k) d propsObj-    PPotato pot -> do-      f' <- toJSVal . fun $ \_ _ ->-        let-          g vnode = do-            vnode' <- valToObject vnode-            stm <- pot . RawNode =<< unsafeGetProp "elm" vnode'-            let go = atomically stm >>= writeUpdate i . hoist (toJSM . runSnabbdom i)-            void $ forkIO go-        in \case-          [vnode]    -> g vnode-          [_, vnode] -> g vnode-          _          -> return ()-      unsafeSetProp "insert" f' hooksObj-      unsafeSetProp "update" f' hooksObj--    PText t -> do-      t' <- toJSVal t-      true <- toJSVal True-      case k of-        "className" | t /= "" -> forM_ (split (== ' ') t) $ \u ->-          if u == mempty then pure () else unsafeSetProp (toJSString u) true classesObj-        "style"     | t /= "" -> unsafeSetProp (toJSString k) t' attrsObj-        "type"      | t /= "" -> unsafeSetProp (toJSString k) t' attrsObj-        "autofocus" | t /= "" -> unsafeSetProp (toJSString k) t' attrsObj-        _                     -> unsafeSetProp (toJSString k) t' propsObj+  flip traverseWithKey_ xs $ \k p ->+    let k' = toJSString k+    in  case p of+      PData d -> unsafeSetProp k' d propsObj+      PPotato pot -> do+        f' <- toJSVal . fun $ \_ _ ->+          let+            g vnode'' = do+              vnode_ <- valToObject vnode''+              stm <- pot . RawNode =<< unsafeGetProp "elm" vnode_+              let go = atomically stm >>= writeUpdate i . hoist (toJSM . runSnabbdom i)+              void $ forkIO go+          in \case+            [vnode_]    -> g vnode_+            [_, vnode_] -> g vnode_+            _           -> return ()+        insertHook "insert" f' hooksObj+        insertHook "update" f' hooksObj+      PText t+        | k == "className" -> forM_ (words t) $ \u ->+            unsafeSetProp (toJSString u) jsTrue classesObj+        | t /= "" -> do+            t' <- valMakeText t+            unsafeSetProp k' t' $ case k of+              "style"                    -> attrsObj+              "type"                     -> attrsObj+              "autofocus"                -> attrsObj+              "checked"                  -> attrsObj+              d | "data-" `isPrefixOf` d -> attrsObj+              _                          -> propsObj+        | otherwise -> do+            t' <- valMakeText t+            unsafeSetProp k' t' propsObj -    PListener f -> do-      f' <- toJSVal . fun $ \_ _ -> \case-        [] -> return ()-        ev:_ -> do-          rn <- unsafeGetProp "target" =<< valToObject ev-          x <- f (RawNode rn) (RawEvent ev)-          writeUpdate i $ hoist (toJSM . runSnabbdom i) x-      unsafeSetProp (toJSString k) f' listenersObj+      PListener f -> do+        f' <- toJSVal . fun $ \_ _ -> \case+          [] -> return ()+          ev:_ -> do+            rn <- unsafeGetProp "target" =<< valToObject ev+            x <- f (RawNode rn) (RawEvent ev)+            writeUpdate i $ hoist (toJSM . runSnabbdom i) x+        unsafeSetProp k' f' listenersObj -    PFlag b -> do-      f <- toJSVal b-      unsafeSetProp (toJSString k) f propsObj+      PFlag b ->+        unsafeSetProp k' (toJSBool b) propsObj    p  <- toJSVal propsObj   l  <- toJSVal listenersObj@@ -173,49 +233,90 @@   return o  -instance (MonadJSM m, Eq a) => Backend (SnabbdomT a) m a where-  type VNode (SnabbdomT a) m = SnabVNode+potato :: JSVal -> RawNode -> JSM ()+#ifndef ghcjs_HOST_OS+potato n rn           = void $ jsg2 "potato" n rn+#else+potato n (RawNode rn) = potato' n rn+foreign import javascript unsafe "window['potato']($1,$2)" potato' :: JSVal -> JSVal -> JSM ()+#endif -  interpret :: (m ~> JSM) -> Html (SnabbdomT a m) a -> SnabbdomT a m SnabVNode-  interpret toJSM = \case -    TextNode t -> liftJSM $ fromJSValUnchecked =<< toJSVal t+vnode :: Text -> Object -> [SnabVNode] -> JSM SnabVNode+#ifndef ghcjs_HOST_OS+vnode name o cs = SnabVNode <$> jsg3 "vnode" name o cs+#else+vnode t o cs    = join $ vnode' <$> pure t <*> pure o <*> toJSVal cs+foreign import javascript unsafe "window['vnode']($1,$2,$3)" vnode' :: Text -> Object -> JSVal -> JSM SnabVNode+#endif -    Node name ps [TextNode t] -> do-      i <- ask; liftJSM $ do-        o <- props toJSM i ps-        fromJSValUnchecked =<< jsg3 "vnode" name o t -    Node name ps children -> do-      i <- ask; liftJSM $ do-        o <- props toJSM i ps-        traverse ((toJSM . runSnabbdom i) . interpret toJSM >=> toJSVal) children-          >>= jsg3 "vnode" name o >>= fromJSValUnchecked+#ifndef ghcjs_HOST_OS+vnodePotato :: Object -> JSM SnabVNode+vnodePotato o = SnabVNode <$> jsg2 "vnode" "div" o+#else+foreign import javascript unsafe "window['vnode']('div',$1)" vnodePotato :: Object -> JSM SnabVNode+#endif -    Potato mrn -> liftJSM $ do-      o <- create-      hook <- create-      rn <- mrn-      ins <- toJSVal =<< function (\_ _ -> \case-        [n] -> void $ jsg2 "potato" n rn-        _   -> return ())-      unsafeSetProp "insert" ins hook-      hoo <- toJSVal hook-      unsafeSetProp "hook" hoo o-      fromJSValUnchecked =<< jsg2 "vnode" "div" o +patchh :: JSVal -> SnabVNode -> JSM ()+#ifndef ghcjs_HOST_OS+patchh previousNode newNode = void $ jsg2 "patchh" previousNode newNode+#else+patchh p (SnabVNode n)      = patchh' p n+foreign import javascript unsafe "window['patchh']($1,$2)" patchh' :: JSVal -> JSVal -> JSM ()+#endif ++instance (MonadJSM m, NFData a) => Backend (SnabbdomT a) m a where+  type VNode (SnabbdomT a) m = SnabVNode++  interpret :: (m ~> JSM) -> Html (SnabbdomT a m) a -> SnabbdomT a m SnabVNode+  interpret toJSM (Html h') = h' mkNode mkPotato mkText+    where+      mkNode name ps children = do+        i <- snabbAsk; liftJSM $ do+          !o <- props toJSM i $ toProps ps+          !cs <- toJSM . runSnabbdom i $ sequence children+          vnode name o cs++      mkPotato mrn = snabbAsk >>= \i -> liftJSM $ do+        o <- create+        hook <- create+        (rn, stm) <- mrn+        ins <- toJSVal =<< function (\_ _ -> \case+          [n] -> potato n rn+          _   -> return ())+        unsafeSetProp "insert" ins hook+        hoo <- toJSVal hook+        unsafeSetProp "hook" hoo o+        let go = atomically stm >>= writeUpdate i . hoist (toJSM . runSnabbdom i) >> go+        void $ forkIO go+        vnodePotato o++      mkText = liftJSM . fmap SnabVNode . valMakeText++   patch :: RawNode -> Maybe SnabVNode -> SnabVNode -> SnabbdomT a m SnabVNode-  patch (RawNode r) f t = t <$ (liftJSM . void $ jsg2 "patchh" f' t)-    where f' = maybe r unVNode f+  patch (RawNode container) mPreviousNode newNode = liftJSM $ newNode <$ patchh previousNode newNode+    where previousNode = maybe container unVNode mPreviousNode     setup :: JSM () -> JSM ()   setup cb = do     void $ eval @Text $(embedStringFile "Shpadoinkle/Backend/Snabbdom/Setup.js")-    void . jsg1 "startApp" . fun $ \_ _ _ -> cb+    startApp cb  +startApp :: JSM () -> JSM ()+#ifndef ghcjs_HOST_OS+startApp cb = void . jsg1 "startApp" . fun $ \_ _ _ -> cb+#else+startApp cb = startApp' =<< toJSVal =<< function (fun $ \_ _ _ -> cb)+foreign import javascript unsafe "window['startApp']($1)" startApp' :: JSVal -> JSM ()+#endif++ -- | Get the @window.container@ DOM node produced by 'setup' (@Setup.js@). stage :: MonadJSM m => SnabbdomT a m RawNode stage = liftJSM $ do@@ -223,6 +324,8 @@   elm <- createElement doc ("div" :: Text)   setAttribute elm ("id" :: Text) ("stage" :: Text)   b <- getBodyUnsafe doc+  setInnerHTML b ""   _ <- appendChild b elm   RawNode <$> toJSVal elm+{-# SPECIALIZE stage :: SnabbdomT a JSM RawNode #-} 
Shpadoinkle/Backend/Snabbdom/Setup.js view
@@ -1,33 +1,22 @@-(() => {--const head = document.getElementsByTagName('head')[0];-const addScript = x => {-  const s = document.createElement('script');-  s.type = 'text/javascript';-  s.src = x;-  head.appendChild(s);-}--const cdnjs = x => "https://cdnjs.cloudflare.com/ajax/libs/snabbdom/0.7.4/" + x;--addScript(cdnjs("snabbdom.min.js"));-addScript(cdnjs("snabbdom-class.min.js"));-addScript(cdnjs("snabbdom-props.min.js"));-addScript(cdnjs("snabbdom-attributes.min.js"));-addScript(cdnjs("snabbdom-eventlisteners.min.js"));-addScript(cdnjs("h.min.js"));--window.startApp = cb => setTimeout(() => {-  const patch = snabbdom.init([-    snabbdom_props.default,-    snabbdom_class.default,-    snabbdom_attributes.default,-    snabbdom_eventlisteners.default-  ]);-  window.patchh = (a,b) => patch(a,b);-  window.vnode = h.default;-  window.potato = (n, e) => n.elm.appendChild(e)-  cb();-}, 1000);--})();+parcelRequire=function(e,r,t,n){var i,o="function"==typeof parcelRequire&&parcelRequire,u="function"==typeof require&&require;function f(t,n){if(!r[t]){if(!e[t]){var i="function"==typeof parcelRequire&&parcelRequire;if(!n&&i)return i(t,!0);if(o)return o(t,!0);if(u&&"string"==typeof t)return u(t);var c=new Error("Cannot find module '"+t+"'");throw c.code="MODULE_NOT_FOUND",c}p.resolve=function(r){return e[t][1][r]||r},p.cache={};var l=r[t]=new f.Module(t);e[t][0].call(l.exports,p,l,l.exports,this)}return r[t].exports;function p(e){return f(p.resolve(e))}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.exports={}},f.modules=e,f.cache=r,f.parent=o,f.register=function(r,t){e[r]=[function(e,r){r.exports=t},{}]};for(var c=0;c<t.length;c++)try{f(t[c])}catch(e){i||(i=e)}if(t.length){var l=f(t[t.length-1]);"object"==typeof exports&&"undefined"!=typeof module?module.exports=l:"function"==typeof define&&define.amd?define(function(){return l}):n&&(this[n]=l)}if(parcelRequire=f,i)throw i;return f}({"RM4J":[function(require,module,exports) {+"use strict";function e(e,t,o,r,d){return{sel:e,data:t,children:o,text:r,elm:d,key:void 0===t?void 0:t.key}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.vnode=e;+},{}],"BfzD":[function(require,module,exports) {+"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.primitive=e,exports.array=void 0;var r=Array.isArray;function e(r){return"string"==typeof r||"number"==typeof r}exports.array=r;+},{}],"VeuO":[function(require,module,exports) {+"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.h=o;var e=require("./vnode.js"),r=i(require("./is.js"));function t(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return t=function(){return e},e}function i(e){if(e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var r=t();if(r&&r.has(e))return r.get(e);var i={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var o in e)if(Object.prototype.hasOwnProperty.call(e,o)){var u=n?Object.getOwnPropertyDescriptor(e,o):null;u&&(u.get||u.set)?Object.defineProperty(i,o,u):i[o]=e[o]}return i.default=e,r&&r.set(e,i),i}function n(e,r,t){if(e.ns="http://www.w3.org/2000/svg","foreignObject"!==t&&void 0!==r)for(var i=0;i<r.length;++i){var o=r[i].data;void 0!==o&&n(o,r[i].children,r[i].sel)}}function o(t,i,o){var u,v,f,a={};if(void 0!==o?(null!==i&&(a=i),r.array(o)?u=o:r.primitive(o)?v=o:o&&o.sel&&(u=[o])):null!=i&&(r.array(i)?u=i:r.primitive(i)?v=i:i&&i.sel?u=[i]:a=i),void 0!==u)for(f=0;f<u.length;++f)r.primitive(u[f])&&(u[f]=(0,e.vnode)(void 0,void 0,void 0,u[f],void 0));return"s"!==t[0]||"v"!==t[1]||"g"!==t[2]||3!==t.length&&"."!==t[3]&&"#"!==t[3]||n(a,u,t),(0,e.vnode)(t,a,u,v,void 0)}+},{"./vnode.js":"RM4J","./is.js":"BfzD"}],"B5vY":[function(require,module,exports) {+"use strict";function e(e,t){return document.createElement(e,t)}function t(e,t,n){return document.createElementNS(e,t,n)}function n(e){return document.createTextNode(e)}function o(e){return document.createComment(e)}function r(e,t,n){e.insertBefore(t,n)}function i(e,t){e.removeChild(t)}function u(e,t){e.appendChild(t)}function c(e){return e.parentNode}function m(e){return e.nextSibling}function d(e){return e.tagName}function a(e,t){e.textContent=t}function f(e){return e.textContent}function l(e){return 1===e.nodeType}function p(e){return 3===e.nodeType}function s(e){return 8===e.nodeType}Object.defineProperty(exports,"__esModule",{value:!0}),exports.htmlDomApi=void 0;var x={createElement:e,createElementNS:t,createTextNode:n,createComment:o,insertBefore:r,removeChild:i,appendChild:u,parentNode:c,nextSibling:m,tagName:d,setTextContent:a,getTextContent:f,isElement:l,isText:p,isComment:s};exports.htmlDomApi=x;+},{}],"FyzG":[function(require,module,exports) {+"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.init=s;var e=require("./vnode.js"),t=l(require("./is.js")),r=require("./htmldomapi.js");function n(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return n=function(){return e},e}function l(e){if(e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var t=n();if(t&&t.has(e))return t.get(e);var r={},l=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var o in e)if(Object.prototype.hasOwnProperty.call(e,o)){var i=l?Object.getOwnPropertyDescriptor(e,o):null;i&&(i.get||i.set)?Object.defineProperty(r,o,i):r[o]=e[o]}return r.default=e,t&&t.set(e,r),r}function o(e){return void 0===e}function i(e){return void 0!==e}var a=(0,e.vnode)("",{},[],void 0,void 0);function d(e,t){var r,n,l=e.key===t.key,o=(null===(r=e.data)||void 0===r?void 0:r.is)===(null===(n=t.data)||void 0===n?void 0:n.is);return e.sel===t.sel&&l&&o}function v(e){return void 0!==e.sel}function u(e,t,r){for(var n,l={},o=t;o<=r;++o){var i=null===(n=e[o])||void 0===n?void 0:n.key;void 0!==i&&(l[i]=o)}return l}var f=["create","update","remove","destroy","pre","post"];function s(n,l){var s,c,p={create:[],update:[],remove:[],destroy:[],pre:[],post:[]},h=void 0!==l?l:r.htmlDomApi;for(s=0;s<f.length;++s)for(p[f[s]]=[],c=0;c<n.length;++c){var m=n[c][f[s]];void 0!==m&&p[f[s]].push(m)}function g(e,t){return function(){if(0==--t){var r=h.parentNode(e);h.removeChild(r,e)}}}function x(e,r){var n,l,d,v=e.data;if(void 0!==v){var u=null===(n=v.hook)||void 0===n?void 0:n.init;i(u)&&(u(e),v=e.data)}var f=e.children,s=e.sel;if("!"===s)o(e.text)&&(e.text=""),e.elm=h.createComment(e.text);else if(void 0!==s){var c=s.indexOf("#"),m=s.indexOf(".",c),g=c>0?c:s.length,y=m>0?m:s.length,k=-1!==c||-1!==m?s.slice(0,Math.min(g,y)):s,b=e.elm=i(v)&&i(d=v.ns)?h.createElementNS(d,k,v):h.createElement(k,v);for(g<y&&b.setAttribute("id",s.slice(g+1,y)),m>0&&b.setAttribute("class",s.slice(y+1).replace(/\./g," ")),d=0;d<p.create.length;++d)p.create[d](a,e);if(t.array(f))for(d=0;d<f.length;++d){var j=f[d];null!=j&&h.appendChild(b,x(j,r))}else t.primitive(e.text)&&h.appendChild(b,h.createTextNode(e.text));var O=e.data.hook;i(O)&&(null===(l=O.create)||void 0===l||l.call(O,a,e),O.insert&&r.push(e))}else e.elm=h.createTextNode(e.text);return e.elm}function y(e,t,r,n,l,o){for(;n<=l;++n){var i=r[n];null!=i&&h.insertBefore(e,x(i,o),t)}}function k(e){var t,r,n=e.data;if(void 0!==n){null===(r=null===(t=null==n?void 0:n.hook)||void 0===t?void 0:t.destroy)||void 0===r||r.call(t,e);for(var l=0;l<p.destroy.length;++l)p.destroy[l](e);if(void 0!==e.children)for(var o=0;o<e.children.length;++o){var i=e.children[o];null!=i&&"string"!=typeof i&&k(i)}}}function b(e,t,r,n){for(var l,o;r<=n;++r){var a=void 0,d=void 0,v=t[r];if(null!=v)if(i(v.sel)){k(v),a=p.remove.length+1,d=g(v.elm,a);for(var u=0;u<p.remove.length;++u)p.remove[u](v,d);var f=null===(o=null===(l=null==v?void 0:v.data)||void 0===l?void 0:l.hook)||void 0===o?void 0:o.remove;i(f)?f(v,d):d()}else h.removeChild(e,v.elm)}}function j(e,t,r){var n,l,a,v,f,s=null===(n=t.data)||void 0===n?void 0:n.hook;null===(l=null==s?void 0:s.prepatch)||void 0===l||l.call(s,e,t);var c=t.elm=e.elm,m=e.children,g=t.children;if(e!==t){if(void 0!==t.data){for(var k=0;k<p.update.length;++k)p.update[k](e,t);null===(v=null===(a=t.data.hook)||void 0===a?void 0:a.update)||void 0===v||v.call(a,e,t)}o(t.text)?i(m)&&i(g)?m!==g&&function(e,t,r,n){for(var l,i,a,v=0,f=0,s=t.length-1,c=t[0],p=t[s],m=r.length-1,g=r[0],k=r[m];v<=s&&f<=m;)null==c?c=t[++v]:null==p?p=t[--s]:null==g?g=r[++f]:null==k?k=r[--m]:d(c,g)?(j(c,g,n),c=t[++v],g=r[++f]):d(p,k)?(j(p,k,n),p=t[--s],k=r[--m]):d(c,k)?(j(c,k,n),h.insertBefore(e,c.elm,h.nextSibling(p.elm)),c=t[++v],k=r[--m]):d(p,g)?(j(p,g,n),h.insertBefore(e,p.elm,c.elm),p=t[--s],g=r[++f]):(void 0===l&&(l=u(t,v,s)),o(i=l[g.key])?h.insertBefore(e,x(g,n),c.elm):(a=t[i]).sel!==g.sel?h.insertBefore(e,x(g,n),c.elm):(j(a,g,n),t[i]=void 0,h.insertBefore(e,a.elm,c.elm)),g=r[++f]);(v<=s||f<=m)&&(v>s?y(e,null==r[m+1]?null:r[m+1].elm,r,f,m,n):b(e,t,v,s))}(c,m,g,r):i(g)?(i(e.text)&&h.setTextContent(c,""),y(c,null,g,0,g.length-1,r)):i(m)?b(c,m,0,m.length-1):i(e.text)&&h.setTextContent(c,""):e.text!==t.text&&(i(m)&&b(c,m,0,m.length-1),h.setTextContent(c,t.text)),null===(f=null==s?void 0:s.postpatch)||void 0===f||f.call(s,e,t)}}return function(t,r){var n,l,o,i=[];for(n=0;n<p.pre.length;++n)p.pre[n]();for(v(t)||(t=function(t){var r=t.id?"#"+t.id:"",n=t.className?"."+t.className.split(" ").join("."):"";return(0,e.vnode)(h.tagName(t).toLowerCase()+r+n,{},[],void 0,t)}(t)),d(t,r)?j(t,r,i):(l=t.elm,o=h.parentNode(l),x(r,i),null!==o&&(h.insertBefore(o,r.elm,h.nextSibling(l)),b(o,[t],0,0))),n=0;n<i.length;++n)i[n].data.hook.insert(i[n]);for(n=0;n<p.post.length;++n)p.post[n]();return r}}+},{"./vnode.js":"RM4J","./is.js":"BfzD","./htmldomapi.js":"B5vY"}],"C4g2":[function(require,module,exports) {+"use strict";function e(e,s){var a,t,o=s.elm,r=e.data.class,l=s.data.class;if((r||l)&&r!==l){for(t in l=l||{},r=r||{})r[t]&&!Object.prototype.hasOwnProperty.call(l,t)&&o.classList.remove(t);for(t in l)(a=l[t])!==r[t]&&o.classList[a?"add":"remove"](t)}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.classModule=void 0;var s={create:e,update:e};exports.classModule=s;+},{}],"FnDi":[function(require,module,exports) {+"use strict";function e(e,o){var r,p,t=o.elm,a=e.data.props,s=o.data.props;if((a||s)&&a!==s)for(r in a=a||{},s=s||{})p=s[r],(a[r]!==p&&("value"!==r||t[r]!==p)||"checked"==r&&t[r]!==p)&&(t[r]=p)}Object.defineProperty(exports,"__esModule",{value:!0}),exports.propsModule=void 0;var o={create:e,update:e};exports.propsModule=o;+},{}],"QBBp":[function(require,module,exports) {+"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.attributesModule=void 0;var t="http://www.w3.org/1999/xlink",e="http://www.w3.org/XML/1998/namespace",r=58,a=120;function i(i,o){var s,u=o.elm,d=i.data.attrs,b=o.data.attrs;if((d||b)&&d!==b){for(s in d=d||{},b=b||{}){var A=b[s];d[s]!==A&&(!0===A?u.setAttribute(s,""):!1===A?u.removeAttribute(s):s.charCodeAt(0)!==a?u.setAttribute(s,A):s.charCodeAt(3)===r?u.setAttributeNS(e,s,A):s.charCodeAt(5)===r?u.setAttributeNS(t,s,A):u.setAttribute(s,A))}for(s in d)s in b||u.removeAttribute(s)}}var o={create:i,update:i};exports.attributesModule=o;+},{}],"HAvm":[function(require,module,exports) {+"use strict";function e(t){return(e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(t)}function t(n,o,r){if("function"==typeof n)n.call(o,r,o);else if("object"===e(n))for(var i=0;i<n.length;i++)t(n[i],o,r)}function n(e,n){var o=e.type,r=n.data.on;r&&r[o]&&t(r[o],n,e)}function o(){return function e(t){n(t,e.vnode)}}function r(e,t){var n,r=e.data.on,i=e.listener,f=e.elm,s=t&&t.data.on,l=t&&t.elm;if(r!==s){if(r&&i)if(s)for(n in r)s[n]||f.removeEventListener(n,i,!1);else for(n in r)f.removeEventListener(n,i,!1);if(s){var u=t.listener=e.listener||o();if(u.vnode=t,r)for(n in s)r[n]||l.addEventListener(n,u,!1);else for(n in s)l.addEventListener(n,u,!1)}}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.eventListenersModule=void 0;var i={create:r,update:r,destroy:r};exports.eventListenersModule=i;+},{}],"gtJM":[function(require,module,exports) {+"use strict";var e=require("./h.js"),r=require("./init.js"),i=require("./modules/class.js"),t=require("./modules/props.js"),n=require("./modules/attributes.js"),s=require("./modules/eventlisteners.js");window.startApp=function(o){var u=(0,r.init)([t.propsModule,i.classModule,n.attributesModule,s.eventListenersModule]);window.patchh=function(e,r){return u(e,r)},window.vnode=e.h,window.potato=function(e,r){return e.elm.appendChild(r)},window.insertHook=function(e,r,i){var t=i[e];i[e]=function(e){t&&t(e),r(e)}},o()};+},{"./h.js":"VeuO","./init.js":"FyzG","./modules/class.js":"C4g2","./modules/props.js":"FnDi","./modules/attributes.js":"QBBp","./modules/eventlisteners.js":"HAvm"}]},{},["gtJM"], null)+//# sourceMappingURL=/Setup_src.js.map