on develop help sign in
Add Prerender
commit14919b5649369bdddebcc3a7e2bba3b766a3d871 authorLuigy Leon <luigy@outlook.com> dateTue 13 Jun 2017, 01:54 (9 years ago) parent0d7665f
5 files changed+99−3
reflex-dom-core/default.nix+3−3 reflex-dom-core/reflex-dom-core.cabal+2 reflex-dom-core/src/Reflex/Dom/Builder/InputDisabled.hs+9 reflex-dom-core/src/Reflex/Dom/Core.hs+1 reflex-dom-core/src/Reflex/Dom/Prerender.hs+84
reflex-dom-core/default.nix+3−3
@@ -1,5 +1,5 @@
11{ mkDerivation, ghc, aeson, base, bifunctors, bimap, blaze-builder
2−, bytestring, containers, contravariant, data-default
2+, bytestring, constraints, containers, contravariant, data-default
33, dependent-map, dependent-sum, dependent-sum-template, directory
44, exception-transformers, ghcjs-dom, hlint, jsaddle, keycode, lens
55, monad-control, mtl, primitive, random, ref-tf, reflex, semigroups
@@ -16,8 +16,8 @@ in mkDerivation (addGcTestDepends {
1616 version = "0.4";
1717 src = ./.;
1818 libraryHaskellDepends = [
19− aeson base bifunctors bimap blaze-builder bytestring containers
20− contravariant data-default dependent-map dependent-sum
19+ aeson base bifunctors bimap blaze-builder bytestring constraints
20+ containers contravariant data-default dependent-map dependent-sum
2121 dependent-sum-template directory exception-transformers ghcjs-dom
2222 jsaddle keycode lens monad-control mtl primitive random ref-tf
2323 reflex semigroups stm template-haskell text these time transformers
reflex-dom-core/reflex-dom-core.cabal+2
@@ -43,6 +43,7 @@ library
4343 blaze-builder,
4444 bytestring == 0.10.*,
4545 containers == 0.5.*,
46+ constraints,
4647 contravariant >= 1.4 && < 1.5,
4748 data-default >= 0.5 && < 0.8,
4849 dependent-map == 0.2.*,
@@ -94,6 +95,7 @@ library
9495 Reflex.Dom.Location
9596 Reflex.Dom.Main
9697 Reflex.Dom.Old
98+ Reflex.Dom.Prerender
9799 Reflex.Dom.Time
98100 Reflex.Dom.WebSocket
99101 Reflex.Dom.Widget
reflex-dom-core/src/Reflex/Dom/Builder/InputDisabled.hs+9
@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
12{-# LANGUAGE FlexibleInstances #-}
23{-# LANGUAGE GeneralizedNewtypeDeriving #-}
34{-# LANGUAGE MultiParamTypeClasses #-}
@@ -15,6 +16,9 @@ import Control.Monad.Trans.Control
1516import Data.Coerce
1617import qualified Data.Map as Map
1718import Foreign.JavaScript.TH
19+#ifndef ghcjs_HOST_OS
20+import GHCJS.DOM.Types (MonadJSM (..))
21+#endif
1822import Reflex
1923import Reflex.Dom.Builder.Class
2024import Reflex.Dom.Builder.Immediate (HasDocument (..))
@@ -26,6 +30,11 @@ import Reflex.Host.Class
2630-- "select" as their tag will NOT be disabled.
2731newtype InputDisabledT m a = InputDisabledT { runInputDisabledT :: m a } deriving (Functor, Applicative, Monad, MonadAtomicRef, MonadFix, MonadIO)
2832
33+#ifndef ghcjs_HOST_OS
34+instance MonadJSM m => MonadJSM (InputDisabledT m) where
35+ liftJSM' = InputDisabledT . liftJSM'
36+#endif
37+
2938deriving instance MonadSample t m => MonadSample t (InputDisabledT m)
3039deriving instance MonadHold t m => MonadHold t (InputDisabledT m)
3140
reflex-dom-core/src/Reflex/Dom/Core.hs+1
@@ -9,6 +9,7 @@ import Reflex.Dom.Class as X
99import Reflex.Dom.Location as X
1010import Reflex.Dom.Main as X
1111import Reflex.Dom.Old as X
12+import Reflex.Dom.Prerender as X
1213import Reflex.Dom.Time as X
1314import Reflex.Dom.WebSocket as X
1415import Reflex.Dom.Widget as X
reflex-dom-core/src/Reflex/Dom/Prerender.hsnew file+84
@@ -0,0 +1,84 @@
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE ConstraintKinds #-}
3+{-# LANGUAGE EmptyDataDecls #-}
4+{-# LANGUAGE FlexibleContexts #-}
5+{-# LANGUAGE FlexibleInstances #-}
6+{-# LANGUAGE FunctionalDependencies #-}
7+{-# LANGUAGE MultiParamTypeClasses #-}
8+{-# LANGUAGE Rank2Types #-}
9+{-# LANGUAGE ScopedTypeVariables #-}
10+{-# LANGUAGE TypeApplications #-}
11+{-# LANGUAGE TypeFamilies #-}
12+{-# LANGUAGE TypeSynonymInstances #-}
13+{-# LANGUAGE UndecidableInstances #-}
14+module Reflex.Dom.Prerender
15+ ( Prerender (..)
16+ , prerender
17+ ) where
18+
19+import Control.Monad.Reader
20+import Data.Constraint
21+import Foreign.JavaScript.TH
22+import GHCJS.DOM.Types (MonadJSM)
23+import Reflex
24+import Reflex.Dom.Builder.InputDisabled
25+import Reflex.Dom.Builder.Immediate
26+import Reflex.Dom.Builder.Static
27+import Reflex.Host.Class
28+
29+type PrerenderClientConstraint js m =
30+ ( HasJS js m
31+ , HasJS js (Performable m)
32+ , MonadJSM m
33+ , MonadJSM (Performable m)
34+ , HasJSContext m
35+ , HasJSContext (Performable m)
36+ , MonadFix m
37+ , MonadFix (Performable m)
38+ )
39+
40+class Prerender js m | m -> js where
41+ prerenderClientDict :: Maybe (Dict (PrerenderClientConstraint js m))
42+
43+-- | Draw one widget when prerendering (e.g. server-side) and another when the
44+-- widget is fully instantiated. In a given execution of this function, there
45+-- will be exactly one invocation of exactly one of the arguments.
46+prerender :: forall js m a. Prerender js m => m a -> (PrerenderClientConstraint js m => m a) -> m a
47+prerender server client = case prerenderClientDict :: Maybe (Dict (PrerenderClientConstraint js m)) of
48+ Nothing -> server
49+ Just Dict -> client
50+
51+instance ( HasJS js m
52+ , HasJS js (Performable m)
53+ , HasJSContext m
54+ , HasJSContext (Performable m)
55+ , MonadJSM m
56+ , MonadJSM (Performable m)
57+ , MonadFix m
58+ , MonadFix (Performable m)
59+ , ReflexHost t
60+ ) => Prerender js (ImmediateDomBuilderT t m) where
61+ prerenderClientDict = Just Dict
62+
63+data NoJavaScript -- This type should never have a HasJS instance
64+
65+instance js ~ NoJavaScript => Prerender js (StaticDomBuilderT t m) where
66+ prerenderClientDict = Nothing
67+
68+instance (Prerender js m, ReflexHost t) => Prerender js (PostBuildT t m) where
69+ prerenderClientDict = fmap (\Dict -> Dict) (prerenderClientDict @js @m)
70+
71+instance Prerender js m => Prerender js (DynamicWriterT t w m) where
72+ prerenderClientDict = fmap (\Dict -> Dict) (prerenderClientDict @js @m)
73+
74+instance Prerender js m => Prerender js (ReaderT w m) where
75+ prerenderClientDict = fmap (\Dict -> Dict) (prerenderClientDict @js @m)
76+
77+instance Prerender js m => Prerender js (RequesterT t request response m) where
78+ prerenderClientDict = fmap (\Dict -> Dict) (prerenderClientDict @js @m)
79+
80+instance Prerender js m => Prerender js (QueryT t q m) where
81+ prerenderClientDict = fmap (\Dict -> Dict) (prerenderClientDict @js @m)
82+
83+instance Prerender js m => Prerender js (InputDisabledT m) where
84+ prerenderClientDict = fmap (\Dict -> Dict) (prerenderClientDict @js @m)