@@ -107,6 +107,9 @@ module Reflex.Dom.Builder.Immediate
107107 , WindowConfig (..)
108108 , Window (..)
109109 , wrapWindow
110+ -- * Attributes for controlling hydration
111+ , hydratableAttribute
112+ , skipHydrationAttribute
110113 -- * Internal
111114 , traverseDMapWithKeyWithAdjust'
112115 , hoistTraverseWithKeyWithAdjust
@@ -137,6 +140,7 @@ import Data.IntMap.Strict (IntMap)
137140import Data.Maybe
138141import Data.Monoid ((<>))
139142import Data.Some (Some(..))
143+import Data.String (IsString)
140144import Data.Text (Text)
141145import Foreign.JavaScript.Internal.Utils
142146import Foreign.JavaScript.TH
@@ -743,6 +747,14 @@ elementInternal elementTag cfg child = getHydrationMode >>= \case
743747 -> HydrationDomBuilderT HydrationDomSpace DomTimeline HydrationM (Element er HydrationDomSpace DomTimeline, a)
744748 #-}
745749
750+-- | An attribute which causes hydration to skip over an element completely.
751+skipHydrationAttribute :: IsString s => s
752+skipHydrationAttribute = "data-hydration-skip"
753+
754+-- | An attribute which signals that an element should be hydrated.
755+hydratableAttribute :: IsString s => s
756+hydratableAttribute = "data-ssr"
757+
746758{-# INLINE hydrateElement #-}
747759hydrateElement
748760 :: forall er t m a. (MonadJSM m, Reflex t, MonadReflexCreateTrigger t m, MonadFix m)
@@ -764,13 +776,15 @@ hydrateElement elementTag cfg child = do
764776 }
765777 result <- HydrationDomBuilderT $ lift $ runReaderT (unHydrationDomBuilderT child) env'
766778 wrapResult <- liftIO newEmptyMVar
767− let skipAttr = "data-hydration-skip" :: DOM.JSString
768− ssrAttr = "data-ssr" :: DOM.JSString
779+ let -- Determine if we should skip an element. We currently skip elements for
780+ -- two reasons:
781+ -- 1) it was not produced by a static builder which supports hydration
782+ -- 2) it is explicitly marked to be skipped
769783 shouldSkip :: DOM.Element -> HydrationRunnerT t m Bool
770784 shouldSkip e = do
771− skip <- hasAttribute e skipAttr
772− ssr <- hasAttribute e ssrAttr
773− pure $ skip || not ssr
785+ skip <- hasAttribute e (skipHydrationAttribute :: DOM.JSString)
786+ hydratable <- hasAttribute e (hydratableAttribute :: DOM.JSString)
787+ pure $ skip || not hydratable
774788 childDom <- liftIO $ readIORef childDelayedRef
775789 let rawCfg = extractRawElementConfig cfg
776790 doc <- askDocument
@@ -786,7 +800,7 @@ hydrateElement elementTag cfg child = do
786800 Just node -> DOM.castTo DOM.Element node >>= \case
787801 Nothing -> go (Just node) -- this node is not an element, skip
788802 Just e -> shouldSkip e >>= \case
789− True -> go (Just node) -- this element is explicitly marked for being skipped by hydration
803+ True -> go (Just node) -- this element should be skipped by hydration
790804 False -> do
791805 t <- Element.getTagName e
792806 -- TODO: check attributes?