Safe Haskell | Safe-Inferred |
---|---|
Language | GHC2021 |
A haskell library for representing web pages.
This library is a collection of web page abstractions, together with a reimagining of suavemente.
I wanted to expose the server delivery mechanism, switch the streaming nature of the gap between a web page and a haskell server, and concentrate on getting a clean interface between pure haskell and the world that is a web page.
See app/examples.hs and Examples
for usage.
Synopsis
- data RepF r a = Rep {}
- type Rep a = RepF (Html ()) a
- oneRep :: Monad m => Rep a -> (Rep a -> HashMap Text Text -> m ()) -> StateT (HashMap Text Text) m (HashMap Text Text, Either Text a)
- newtype SharedRepF m r a = SharedRep {}
- type SharedRep m a = SharedRepF m (Html ()) a
- runOnce :: Monad m => SharedRep m a -> (Html () -> HashMap Text Text -> m ()) -> m (HashMap Text Text, Either Text a)
- zeroState :: Monad m => SharedRep m a -> m (Html (), (HashMap Text Text, Either Text a))
- register :: Monad m => (Text -> Either Text a) -> (a -> Text) -> (Text -> a -> r) -> a -> SharedRepF m r a
- genName :: MonadState Int m => m Text
- genNamePre :: MonadState Int m => Text -> m Text
- data Page = Page {}
- data PageConfig = PageConfig {}
- defaultPageConfig :: FilePath -> PageConfig
- data Concerns a = Concerns {
- cssConcern :: a
- jsConcern :: a
- htmlConcern :: a
- suffixes :: Concerns FilePath
- concernNames :: FilePath -> FilePath -> Concerns FilePath
- data PageConcerns
- data PageStructure
- = HeaderBody
- | Headless
- | Snippet
- | Svg
- data PageRender
- type Css = StyleM ()
- data RepCss
- = RepCss Css
- | RepCssText Text
- renderCss :: Css -> Text
- renderRepCss :: PageRender -> RepCss -> Text
- newtype JS = JS {}
- data RepJs
- onLoad :: RepJs -> RepJs
- renderRepJs :: PageRender -> RepJs -> Text
- parseJs :: Text -> JS
- renderJs :: JS -> Text
- module Web.Rep.SharedReps
- module Web.Rep.Render
- module Web.Rep.Server
- module Web.Rep.Socket
- module Web.Rep.Html
- module Web.Rep.Html.Input
- module Web.Rep.Bootstrap
- data HashMap k v
Shared Representation
Information contained in a web page can usually be considered to be isomorphic to a map of named values - a HashMap
. This is especially true when considering a differential of information contained in a web page. Looking at a page from the outside, it often looks like a streaming differential of a hashmap.
RepF consists of an underlying value being represented, and, given a hashmap state, a way to produce a representation of the underlying value (or error), in another domain, together with the potential to alter the hashmap state.
oneRep :: Monad m => Rep a -> (Rep a -> HashMap Text Text -> m ()) -> StateT (HashMap Text Text) m (HashMap Text Text, Either Text a) Source #
stateful result of one step, given a RepF
, and a monadic action.
Useful for testing and for initialising a page.
newtype SharedRepF m r a Source #
Driven by the architecture of the DOM, web page components are compositional, and tree-like, where components are often composed of other components, and values are thus shared across components.
This is sometimes referred to as "observable sharing". See data-reify as another library that reifies this (pun intended), and provided the initial inspiration for this implementation.
unshare should only be run once, which is a terrible flaw that might be fixed by linear types.
Instances
runOnce :: Monad m => SharedRep m a -> (Html () -> HashMap Text Text -> m ()) -> m (HashMap Text Text, Either Text a) Source #
Compute the initial state of a SharedRep and then run an action once (see tests).
zeroState :: Monad m => SharedRep m a -> m (Html (), (HashMap Text Text, Either Text a)) Source #
compute the initial state of a SharedRep (testing)
:: Monad m | |
=> (Text -> Either Text a) | Parser |
-> (a -> Text) | Printer |
-> (Text -> a -> r) | create initial object from name and initial value |
-> a | initial value |
-> SharedRepF m r a |
Create a sharedRep
genName :: MonadState Int m => m Text Source #
name supply for elements of a SharedRepF
genNamePre :: MonadState Int m => Text -> m Text Source #
sometimes a number doesn't work properly in html (or js???), and an alpha prefix seems to help
Web Rep Components
Components of a web page.
A web page can take many forms but still have the same underlying representation. For example, CSS can be linked to in a separate file, or can be inline within html, but still be the same css and have the same expected external effect. A Page represents the practical components of what makes up a static snapshot of a web page.
Instances
data PageConfig Source #
Configuration options when rendering a Page
.
PageConfig | |
|
Instances
defaultPageConfig :: FilePath -> PageConfig Source #
Default configuration is inline ecma and css, separate html header and body, minified code, with the suggested filename prefix.
A web page typically is composed of some css, javascript and html.
Concerns
abstracts this structural feature of a web page.
Concerns | |
|
Instances
concernNames :: FilePath -> FilePath -> Concerns FilePath Source #
Create filenames for each Concern element.
data PageConcerns Source #
Is the rendering to include all Concerns
(typically in a html file) or be separated (tyypically into separate files and linked in the html file)?
Instances
Generic PageConcerns Source # | |
Defined in Web.Rep.Page type Rep PageConcerns :: Type -> Type # from :: PageConcerns -> Rep PageConcerns x # to :: Rep PageConcerns x -> PageConcerns # | |
Show PageConcerns Source # | |
Defined in Web.Rep.Page showsPrec :: Int -> PageConcerns -> ShowS # show :: PageConcerns -> String # showList :: [PageConcerns] -> ShowS # | |
Eq PageConcerns Source # | |
Defined in Web.Rep.Page (==) :: PageConcerns -> PageConcerns -> Bool # (/=) :: PageConcerns -> PageConcerns -> Bool # | |
type Rep PageConcerns Source # | |
data PageStructure Source #
Various ways that a Html file can be structured.
Instances
Generic PageStructure Source # | |
Defined in Web.Rep.Page type Rep PageStructure :: Type -> Type # from :: PageStructure -> Rep PageStructure x # to :: Rep PageStructure x -> PageStructure # | |
Show PageStructure Source # | |
Defined in Web.Rep.Page showsPrec :: Int -> PageStructure -> ShowS # show :: PageStructure -> String # showList :: [PageStructure] -> ShowS # | |
Eq PageStructure Source # | |
Defined in Web.Rep.Page (==) :: PageStructure -> PageStructure -> Bool # (/=) :: PageStructure -> PageStructure -> Bool # | |
type Rep PageStructure Source # | |
Defined in Web.Rep.Page type Rep PageStructure = D1 ('MetaData "PageStructure" "Web.Rep.Page" "web-rep-0.10.2.0-B2YHxkxT2gHDHhcJpNYihj" 'False) ((C1 ('MetaCons "HeaderBody" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "Headless" 'PrefixI 'False) (U1 :: Type -> Type)) :+: (C1 ('MetaCons "Snippet" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "Svg" 'PrefixI 'False) (U1 :: Type -> Type))) |
data PageRender Source #
Post-processing of page concerns
Instances
Generic PageRender Source # | |
Defined in Web.Rep.Page type Rep PageRender :: Type -> Type # from :: PageRender -> Rep PageRender x # to :: Rep PageRender x -> PageRender # | |
Show PageRender Source # | |
Defined in Web.Rep.Page showsPrec :: Int -> PageRender -> ShowS # show :: PageRender -> String # showList :: [PageRender] -> ShowS # | |
Eq PageRender Source # | |
Defined in Web.Rep.Page (==) :: PageRender -> PageRender -> Bool # (/=) :: PageRender -> PageRender -> Bool # | |
type Rep PageRender Source # | |
Defined in Web.Rep.Page type Rep PageRender = D1 ('MetaData "PageRender" "Web.Rep.Page" "web-rep-0.10.2.0-B2YHxkxT2gHDHhcJpNYihj" 'False) (C1 ('MetaCons "Pretty" 'PrefixI 'False) (U1 :: Type -> Type) :+: (C1 ('MetaCons "Minified" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "NoPost" 'PrefixI 'False) (U1 :: Type -> Type))) |
Css
Unifies css as either a Css
or as Text.
Instances
Monoid RepCss Source # | |
Semigroup RepCss Source # | |
Generic RepCss Source # | |
Show RepCss Source # | |
type Rep RepCss Source # | |
Defined in Web.Rep.Page type Rep RepCss = D1 ('MetaData "RepCss" "Web.Rep.Page" "web-rep-0.10.2.0-B2YHxkxT2gHDHhcJpNYihj" 'False) (C1 ('MetaCons "RepCss" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Css)) :+: C1 ('MetaCons "RepCssText" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Text))) |
renderRepCss :: PageRender -> RepCss -> Text Source #
Render RepCss
as text.
JS
wrapper for JSAST
Unifies javascript as JSStatement
and script as Text
.
Instances
Monoid RepJs Source # | |
Semigroup RepJs Source # | |
Generic RepJs Source # | |
Show RepJs Source # | |
Eq RepJs Source # | |
type Rep RepJs Source # | |
Defined in Web.Rep.Page type Rep RepJs = D1 ('MetaData "RepJs" "Web.Rep.Page" "web-rep-0.10.2.0-B2YHxkxT2gHDHhcJpNYihj" 'False) (C1 ('MetaCons "RepJs" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 JS)) :+: C1 ('MetaCons "RepJsText" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Text))) |
renderRepJs :: PageRender -> RepJs -> Text Source #
re-export modules
module Web.Rep.SharedReps
module Web.Rep.Render
module Web.Rep.Server
module Web.Rep.Socket
module Web.Rep.Html
module Web.Rep.Html.Input
module Web.Rep.Bootstrap
re-exports
A map from keys to values. A map cannot contain duplicate keys; each key can map to at most one value.
Instances
Bifoldable HashMap | Since: unordered-containers-0.2.11 |
Eq2 HashMap | |
Ord2 HashMap | |
Defined in Data.HashMap.Internal | |
Show2 HashMap | |
NFData2 HashMap | Since: unordered-containers-0.2.14.0 |
Defined in Data.HashMap.Internal | |
Hashable2 HashMap | |
Defined in Data.HashMap.Internal | |
(Lift k, Lift v) => Lift (HashMap k v :: Type) | Since: unordered-containers-0.2.17.0 |
Foldable (HashMap k) | |
Defined in Data.HashMap.Internal fold :: Monoid m => HashMap k m -> m # foldMap :: Monoid m => (a -> m) -> HashMap k a -> m # foldMap' :: Monoid m => (a -> m) -> HashMap k a -> m # foldr :: (a -> b -> b) -> b -> HashMap k a -> b # foldr' :: (a -> b -> b) -> b -> HashMap k a -> b # foldl :: (b -> a -> b) -> b -> HashMap k a -> b # foldl' :: (b -> a -> b) -> b -> HashMap k a -> b # foldr1 :: (a -> a -> a) -> HashMap k a -> a # foldl1 :: (a -> a -> a) -> HashMap k a -> a # toList :: HashMap k a -> [a] # length :: HashMap k a -> Int # elem :: Eq a => a -> HashMap k a -> Bool # maximum :: Ord a => HashMap k a -> a # minimum :: Ord a => HashMap k a -> a # | |
Eq k => Eq1 (HashMap k) | |
Ord k => Ord1 (HashMap k) | |
Defined in Data.HashMap.Internal | |
(Eq k, Hashable k, Read k) => Read1 (HashMap k) | |
Defined in Data.HashMap.Internal | |
Show k => Show1 (HashMap k) | |
Traversable (HashMap k) | |
Functor (HashMap k) | |
NFData k => NFData1 (HashMap k) | Since: unordered-containers-0.2.14.0 |
Defined in Data.HashMap.Internal | |
Hashable k => Hashable1 (HashMap k) | |
Defined in Data.HashMap.Internal | |
(Data k, Data v, Eq k, Hashable k) => Data (HashMap k v) | |
Defined in Data.HashMap.Internal gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> HashMap k v -> c (HashMap k v) # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (HashMap k v) # toConstr :: HashMap k v -> Constr # dataTypeOf :: HashMap k v -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (HashMap k v)) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (HashMap k v)) # gmapT :: (forall b. Data b => b -> b) -> HashMap k v -> HashMap k v # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> HashMap k v -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> HashMap k v -> r # gmapQ :: (forall d. Data d => d -> u) -> HashMap k v -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> HashMap k v -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> HashMap k v -> m (HashMap k v) # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> HashMap k v -> m (HashMap k v) # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> HashMap k v -> m (HashMap k v) # | |
(Eq k, Hashable k) => Monoid (HashMap k v) | If a key occurs in both maps, the mapping from the first will be the mapping in the result. Examples
|
(Eq k, Hashable k) => Semigroup (HashMap k v) | If a key occurs in both maps, the mapping from the first will be the mapping in the result. Examples
|
(Eq k, Hashable k) => IsList (HashMap k v) | |
(Eq k, Hashable k, Read k, Read e) => Read (HashMap k e) | |
(Show k, Show v) => Show (HashMap k v) | |
(NFData k, NFData v) => NFData (HashMap k v) | |
Defined in Data.HashMap.Internal | |
(Eq k, Eq v) => Eq (HashMap k v) | Note that, in the presence of hash collisions, equal
In general, the lack of substitutivity can be observed with any function that depends on the key ordering, such as folds and traversals. |
(Ord k, Ord v) => Ord (HashMap k v) | The ordering is total and consistent with the |
Defined in Data.HashMap.Internal | |
(Hashable k, Hashable v) => Hashable (HashMap k v) | |
Defined in Data.HashMap.Internal | |
type Item (HashMap k v) | |
Defined in Data.HashMap.Internal |