{-# HLINT ignore "Avoid lambda using `infix`" #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
module Language.Ltml.HTML.Common
(
HtmlReaderState
, ReaderStateMonad
, runReaderState
, GlobalState (..)
, ReaderState (..)
, initGlobalState
, initReaderState
, incSectionID
, incInsertedSectionID
, resetInsertedSectionID
, incSuperSectionID
, FootnoteMap
, convertLabelMap
, addUsedFootnotes
, FootnoteSet
, NumLabel (..)
, ToC
, TocEntry
, TocCategory (..)
, addTocEntry
, addPhantomTocEntry
, PhantomTocEntry
, RenderedTocEntry
, Result (..)
, result
, EnumStyleMap
, LabelWrapper
, TocEntryWrapper
, anchorLink
, pageLink
, mainPageAnchorLink
, collectExportSection
, exportLink
, setHasErrors
, Delayed (..)
, evalDelayed
, returnNow
) where
import Control.Monad.Reader (ReaderT, runReaderT)
import Control.Monad.State (State, get, modify, runState)
import Data.Aeson (FromJSON, ToJSON)
import Data.ByteString.Lazy (ByteString)
import Data.DList (DList, snoc)
import qualified Data.DList as DList (empty)
import Data.Map (Map)
import qualified Data.Map as Map (empty)
import Data.OpenApi (ToSchema)
import Data.Set (Set)
import qualified Data.Set as Set (empty)
import Data.Text (Text, cons, pack)
import GHC.Generics (Generic)
import Language.Lsd.AST.Common (Fallback, NavTocHeading)
import Language.Lsd.AST.Format
import Language.Lsd.AST.Type.Enum (EnumFormat)
import Language.Lsd.AST.Type.Section (SectionFormat)
import Language.Ltml.AST.Footnote (Footnote)
import Language.Ltml.AST.Label (Label (unLabel))
import qualified Language.Ltml.HTML.CSS.Classes as Class
import Language.Ltml.HTML.CSS.Util (cssClass_, (<#>))
import Lucid (Html, a_, div_, href_, span_, toHtml)
type HtmlReaderState = ReaderStateMonad (Delayed (Html ()))
type ReaderStateMonad a = ReaderT ReaderState (State GlobalState) a
runReaderState
:: ReaderStateMonad a -> ReaderState -> GlobalState -> (a, GlobalState)
runReaderState :: forall a.
ReaderStateMonad a
-> ReaderState -> GlobalState -> (a, GlobalState)
runReaderState ReaderStateMonad a
ma ReaderState
readerState = State GlobalState a -> GlobalState -> (a, GlobalState)
forall s a. State s a -> s -> (a, s)
runState (ReaderStateMonad a -> ReaderState -> State GlobalState a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT ReaderStateMonad a
ma ReaderState
readerState)
data GlobalState = GlobalState
{ GlobalState -> Bool
hasFlagged :: Bool
, GlobalState -> Int
currentSuperSectionID :: Int
, GlobalState -> Int
currentSectionID :: Int
, GlobalState -> Int
currentInsertedSectionID :: Int
, GlobalState -> Int
currentParagraphID :: Int
, GlobalState -> Int
currentSentenceID :: Int
, GlobalState -> Int
currentEnumItemID :: Int
, :: Int
, :: FootnoteMap
, :: FootnoteSet
, GlobalState -> [(Label, HtmlT Identity ())]
labels :: [(Label, Html ())]
, GlobalState -> ToC
tableOfContents :: ToC
, GlobalState -> Text
mangledLabelName :: Text
, GlobalState -> Int
mangledLabelID :: Int
, GlobalState -> EnumStyleMap
enumStyles :: EnumStyleMap
, GlobalState -> Text
mangledEnumCounterName :: Text
, GlobalState -> Int
mangledEnumCounterID :: Int
, GlobalState -> [(Text, Delayed Text, Delayed (HtmlT Identity ()))]
exportSections :: [(Text, Delayed Text, Delayed (Html ()))]
, GlobalState -> Fallback NavTocHeading
documentFallbackTitle :: Fallback NavTocHeading
, GlobalState -> Delayed (HtmlT Identity ())
mainDocumentTitleHtml :: Delayed (Html ())
, GlobalState -> Delayed Text
mainDocumentTitle :: Delayed Text
, GlobalState -> Bool
hasErrors :: Bool
}
data ReaderState = ReaderState
{ ReaderState -> Bool
shouldRender :: Bool
, ReaderState -> Bool
hasGlobalToC :: Bool
, ReaderState -> Bool
appendixHasGlobalToC :: Bool
, ReaderState -> Int
currentAppendixElementID :: Int
, ReaderState -> IdentifierFormat
appendixElementIdFormat :: IdentifierFormat
, ReaderState -> TocKeyFormat
appendixElementTocKeyFormat :: TocKeyFormat
, ReaderState -> Maybe Label
appendixElementMLabel :: Maybe Label
, ReaderState -> Either (HeadingFormat 'False) (HeadingFormat 'True)
documentHeadingFormat :: Either (HeadingFormat False) (HeadingFormat True)
, ReaderState -> SectionFormat
localSectionFormat :: SectionFormat
, ReaderState -> Bool
isSingleParagraph :: Bool
, ReaderState -> IdentifierFormat
currentEnumIDFormatString :: IdentifierFormat
, :: Map Label Footnote
, ReaderState -> LabelWrapper
labelWrapperFunc :: LabelWrapper
, :: LabelWrapper
, ReaderState -> TocEntryWrapper
tocEntryWrapperFunc :: TocEntryWrapper
, ReaderState -> TocEntryWrapper
tocButtonWrapperFunc :: TocEntryWrapper
, ReaderState -> LabelWrapper
exportLinkWrapper :: LabelWrapper
}
initGlobalState :: GlobalState
initGlobalState :: GlobalState
initGlobalState =
GlobalState
{ hasFlagged :: Bool
hasFlagged = Bool
False
, currentSuperSectionID :: Int
currentSuperSectionID = Int
1
, currentSectionID :: Int
currentSectionID = Int
0
, currentInsertedSectionID :: Int
currentInsertedSectionID = Int
0
, currentParagraphID :: Int
currentParagraphID = Int
1
, currentSentenceID :: Int
currentSentenceID = Int
0
, currentEnumItemID :: Int
currentEnumItemID = Int
1
, currentFootnoteID :: Int
currentFootnoteID = Int
1
, usedFootnoteMap :: FootnoteMap
usedFootnoteMap = []
, locallyUsedFootnotes :: FootnoteSet
locallyUsedFootnotes = FootnoteSet
forall a. Set a
Set.empty
, labels :: [(Label, HtmlT Identity ())]
labels = []
, tableOfContents :: ToC
tableOfContents = ToC
forall a. DList a
DList.empty
, mangledLabelName :: Text
mangledLabelName = Text
"_TOC_ENTRY_"
, mangledLabelID :: Int
mangledLabelID = Int
0
, enumStyles :: EnumStyleMap
enumStyles = []
, mangledEnumCounterName :: Text
mangledEnumCounterName = Text
"_ENUM_STYLE_"
, mangledEnumCounterID :: Int
mangledEnumCounterID = Int
0
, exportSections :: [(Text, Delayed Text, Delayed (HtmlT Identity ()))]
exportSections = []
, documentFallbackTitle :: Fallback NavTocHeading
documentFallbackTitle = [Char] -> Fallback NavTocHeading
forall a. HasCallStack => [Char] -> a
error [Char]
"Undefined Main Document Fallback Heading!"
, mainDocumentTitleHtml :: Delayed (HtmlT Identity ())
mainDocumentTitleHtml = Delayed (HtmlT Identity ())
forall a. Monoid a => a
mempty
, mainDocumentTitle :: Delayed Text
mainDocumentTitle = Delayed Text
forall a. Monoid a => a
mempty
, hasErrors :: Bool
hasErrors = Bool
False
}
initReaderState :: ReaderState
initReaderState :: ReaderState
initReaderState =
ReaderState
{ shouldRender :: Bool
shouldRender = Bool
False
, hasGlobalToC :: Bool
hasGlobalToC = Bool
False
, appendixHasGlobalToC :: Bool
appendixHasGlobalToC = Bool
False
, currentAppendixElementID :: Int
currentAppendixElementID = Int
1
, appendixElementIdFormat :: IdentifierFormat
appendixElementIdFormat = [Char] -> IdentifierFormat
forall a. HasCallStack => [Char] -> a
error [Char]
"Undefined appendix element id format!"
, appendixElementTocKeyFormat :: TocKeyFormat
appendixElementTocKeyFormat = [Char] -> TocKeyFormat
forall a. HasCallStack => [Char] -> a
error [Char]
"Undefined appendix element ToC format!"
, appendixElementMLabel :: Maybe Label
appendixElementMLabel = Maybe Label
forall a. Maybe a
Nothing
, documentHeadingFormat :: Either (HeadingFormat 'False) (HeadingFormat 'True)
documentHeadingFormat = [Char] -> Either (HeadingFormat 'False) (HeadingFormat 'True)
forall a. HasCallStack => [Char] -> a
error [Char]
"Undefined HeadingFormat!"
, localSectionFormat :: SectionFormat
localSectionFormat = [Char] -> SectionFormat
forall a. HasCallStack => [Char] -> a
error [Char]
"Undefined SectionFormat!"
, isSingleParagraph :: Bool
isSingleParagraph = Bool
False
, currentEnumIDFormatString :: IdentifierFormat
currentEnumIDFormatString = [Char] -> IdentifierFormat
forall a. HasCallStack => [Char] -> a
error [Char]
"Undefined enum id format!"
, footnoteMap :: Map Label Footnote
footnoteMap = Map Label Footnote
forall k a. Map k a
Map.empty
,
labelWrapperFunc :: LabelWrapper
labelWrapperFunc = (HtmlT Identity () -> HtmlT Identity ()) -> LabelWrapper
forall a b. a -> b -> a
const HtmlT Identity () -> HtmlT Identity ()
forall a. a -> a
id
, footnoteWrapperFunc :: LabelWrapper
footnoteWrapperFunc = (HtmlT Identity () -> HtmlT Identity ()) -> LabelWrapper
forall a b. a -> b -> a
const HtmlT Identity () -> HtmlT Identity ()
forall a. a -> a
id
, tocEntryWrapperFunc :: TocEntryWrapper
tocEntryWrapperFunc = LabelWrapper -> TocEntryWrapper
forall a b. a -> b -> a
const (LabelWrapper -> TocEntryWrapper)
-> LabelWrapper -> TocEntryWrapper
forall a b. (a -> b) -> a -> b
$ (HtmlT Identity () -> HtmlT Identity ()) -> LabelWrapper
forall a b. a -> b -> a
const HtmlT Identity () -> HtmlT Identity ()
forall a. a -> a
id
, tocButtonWrapperFunc :: TocEntryWrapper
tocButtonWrapperFunc = LabelWrapper -> TocEntryWrapper
forall a b. a -> b -> a
const LabelWrapper
anchorLink
, exportLinkWrapper :: LabelWrapper
exportLinkWrapper = (HtmlT Identity () -> HtmlT Identity ()) -> LabelWrapper
forall a b. a -> b -> a
const HtmlT Identity () -> HtmlT Identity ()
forall a. Monoid a => a
mempty
}
incSectionID :: ReaderT r (State GlobalState) ()
incSectionID :: forall r. ReaderT r (State GlobalState) ()
incSectionID = (GlobalState -> GlobalState) -> ReaderT r (State GlobalState) ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify (\GlobalState
s -> GlobalState
s {currentSectionID = currentSectionID s + 1})
incInsertedSectionID :: ReaderT r (State GlobalState) ()
incInsertedSectionID :: forall r. ReaderT r (State GlobalState) ()
incInsertedSectionID = (GlobalState -> GlobalState) -> ReaderT r (State GlobalState) ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify (\GlobalState
s -> GlobalState
s {currentInsertedSectionID = currentInsertedSectionID s + 1})
resetInsertedSectionID :: ReaderT r (State GlobalState) ()
resetInsertedSectionID :: forall r. ReaderT r (State GlobalState) ()
resetInsertedSectionID =
(GlobalState -> GlobalState) -> ReaderT r (State GlobalState) ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify
(\GlobalState
s -> GlobalState
s {currentInsertedSectionID = currentInsertedSectionID initGlobalState})
incSuperSectionID :: ReaderT r (State GlobalState) ()
incSuperSectionID :: forall r. ReaderT r (State GlobalState) ()
incSuperSectionID = (GlobalState -> GlobalState) -> ReaderT r (State GlobalState) ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify (\GlobalState
s -> GlobalState
s {currentSuperSectionID = currentSuperSectionID s + 1})
type = [(Label, (Int, Html (), Delayed (Html ())))]
convertLabelMap :: FootnoteMap -> [(Label, Html ())]
convertLabelMap :: FootnoteMap -> [(Label, HtmlT Identity ())]
convertLabelMap = ((Label, (Int, HtmlT Identity (), Delayed (HtmlT Identity ())))
-> (Label, HtmlT Identity ()))
-> FootnoteMap -> [(Label, HtmlT Identity ())]
forall a b. (a -> b) -> [a] -> [b]
map (\(Label
label, (Int
_, HtmlT Identity ()
idHtml, Delayed (HtmlT Identity ())
_)) -> (Label
label, HtmlT Identity ()
idHtml))
addUsedFootnotes
:: GlobalState
-> GlobalState
-> GlobalState
GlobalState
base GlobalState
add =
GlobalState
base
{ locallyUsedFootnotes = locallyUsedFootnotes add <> locallyUsedFootnotes base
}
type = Set NumLabel
newtype NumLabel = NumLabel {NumLabel -> (Int, Label)
unNumLabel :: (Int, Label)}
instance Eq NumLabel where
(NumLabel (Int
a, Label
_)) == :: NumLabel -> NumLabel -> Bool
== (NumLabel (Int
b, Label
_)) = Int
a Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
b
instance Ord NumLabel where
compare :: NumLabel -> NumLabel -> Ordering
compare (NumLabel (Int
a, Label
_)) (NumLabel (Int
b, Label
_)) = Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Int
a Int
b
type ToC = DList (Either PhantomTocEntry TocEntry)
type TocEntry = (Maybe (Html ()), Result (Delayed (Html ())), Text, TocCategory)
data TocCategory = SomeSection | Other
type PhantomTocEntry = (Maybe (Html ()), Result (Html ()))
addTocEntry
:: Maybe (Html ())
-> Result (Delayed (Html ()))
-> Maybe Label
-> TocCategory
-> ReaderStateMonad Text
addTocEntry :: Maybe (HtmlT Identity ())
-> Result (Delayed (HtmlT Identity ()))
-> Maybe Label
-> TocCategory
-> ReaderStateMonad Text
addTocEntry Maybe (HtmlT Identity ())
mKey Result (Delayed (HtmlT Identity ()))
title Maybe Label
mLabel TocCategory
cat = do
GlobalState
globalState <- ReaderT ReaderState (State GlobalState) GlobalState
forall s (m :: * -> *). MonadState s m => m s
get
Text
htmlId <- case Maybe Label
mLabel of
Maybe Label
Nothing ->
let mangledLabel :: Text
mangledLabel = GlobalState -> Text
mangledLabelName GlobalState
globalState Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
pack (Int -> [Char]
forall a. Show a => a -> [Char]
show (GlobalState -> Int
mangledLabelID GlobalState
globalState))
in do
(GlobalState -> GlobalState)
-> ReaderT ReaderState (State GlobalState) ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify (\GlobalState
s -> GlobalState
s {mangledLabelID = mangledLabelID s + 1})
Text -> ReaderStateMonad Text
forall a. a -> ReaderT ReaderState (State GlobalState) a
forall (m :: * -> *) a. Monad m => a -> m a
return Text
mangledLabel
Just Label
label -> Text -> ReaderStateMonad Text
forall a. a -> ReaderT ReaderState (State GlobalState) a
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> ReaderStateMonad Text) -> Text -> ReaderStateMonad Text
forall a b. (a -> b) -> a -> b
$ Label -> Text
unLabel Label
label
(GlobalState -> GlobalState)
-> ReaderT ReaderState (State GlobalState) ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify
( \GlobalState
s ->
GlobalState
s
{ tableOfContents = snoc (tableOfContents s) (Right (mKey, title, htmlId, cat))
}
)
Text -> ReaderStateMonad Text
forall a. a -> ReaderT ReaderState (State GlobalState) a
forall (m :: * -> *) a. Monad m => a -> m a
return Text
htmlId
addPhantomTocEntry
:: Result (Html ()) -> ReaderStateMonad ()
addPhantomTocEntry :: Result (HtmlT Identity ())
-> ReaderT ReaderState (State GlobalState) ()
addPhantomTocEntry Result (HtmlT Identity ())
resHtml =
let tocEntry :: (Maybe a, Result (HtmlT Identity ()))
tocEntry = (Maybe a
forall a. Maybe a
Nothing, Result (HtmlT Identity ())
resHtml)
in (GlobalState -> GlobalState)
-> ReaderT ReaderState (State GlobalState) ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify (\GlobalState
s -> GlobalState
s {tableOfContents = snoc (tableOfContents s) (Left tocEntry)})
type RenderedTocEntry = (Maybe ByteString, Result ByteString)
data Result a = Success a | Error a
deriving (Int -> Result a -> ShowS
[Result a] -> ShowS
Result a -> [Char]
(Int -> Result a -> ShowS)
-> (Result a -> [Char]) -> ([Result a] -> ShowS) -> Show (Result a)
forall a. Show a => Int -> Result a -> ShowS
forall a. Show a => [Result a] -> ShowS
forall a. Show a => Result a -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> Result a -> ShowS
showsPrec :: Int -> Result a -> ShowS
$cshow :: forall a. Show a => Result a -> [Char]
show :: Result a -> [Char]
$cshowList :: forall a. Show a => [Result a] -> ShowS
showList :: [Result a] -> ShowS
Show, (forall x. Result a -> Rep (Result a) x)
-> (forall x. Rep (Result a) x -> Result a) -> Generic (Result a)
forall x. Rep (Result a) x -> Result a
forall x. Result a -> Rep (Result a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Result a) x -> Result a
forall a x. Result a -> Rep (Result a) x
$cfrom :: forall a x. Result a -> Rep (Result a) x
from :: forall x. Result a -> Rep (Result a) x
$cto :: forall a x. Rep (Result a) x -> Result a
to :: forall x. Rep (Result a) x -> Result a
Generic)
instance (ToJSON a) => ToJSON (Result a)
instance (FromJSON a) => FromJSON (Result a)
instance (ToSchema a) => ToSchema (Result a)
result :: (a -> b) -> (a -> b) -> Result a -> b
result :: forall a b. (a -> b) -> (a -> b) -> Result a -> b
result a -> b
fSuc a -> b
fErr Result a
res = case Result a
res of
Success a
a -> a -> b
fSuc a
a
Error a
a -> a -> b
fErr a
a
instance Functor Result where
fmap :: forall a b. (a -> b) -> Result a -> Result b
fmap a -> b
f (Success a
a) = b -> Result b
forall a. a -> Result a
Success (a -> b
f a
a)
fmap a -> b
f (Error a
a) = b -> Result b
forall a. a -> Result a
Error (a -> b
f a
a)
type EnumStyleMap = [(EnumFormat, Text)]
type LabelWrapper = Label -> Html () -> Html ()
type TocEntryWrapper = TocCategory -> LabelWrapper
anchorLink :: LabelWrapper
anchorLink :: LabelWrapper
anchorLink Label
label =
[Attributes] -> HtmlT Identity () -> HtmlT Identity ()
forall arg result. Term arg result => arg -> result
a_
[ Class -> Attributes
cssClass_ Class
Class.AnchorLink
, Text -> Attributes
href_ (Char -> Text -> Text
cons Char
'#' (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ Label -> Text
unLabel Label
label)
]
pageLink
:: FilePath
-> TocEntryWrapper
pageLink :: [Char] -> TocEntryWrapper
pageLink [Char]
_ TocCategory
Other Label
_ = HtmlT Identity () -> HtmlT Identity () -> HtmlT Identity ()
forall a b. a -> b -> a
const HtmlT Identity ()
forall a. Monoid a => a
mempty
pageLink [Char]
path TocCategory
_ Label
label =
[Attributes] -> HtmlT Identity () -> HtmlT Identity ()
forall arg result. Term arg result => arg -> result
a_ [Class -> Attributes
cssClass_ Class
Class.ButtonLink, Text -> Attributes
href_ ([Char] -> Label -> Text
labelPath [Char]
path Label
label)]
mainPageAnchorLink :: FilePath -> LabelWrapper
mainPageAnchorLink :: [Char] -> LabelWrapper
mainPageAnchorLink [Char]
path Label
label = [Attributes] -> HtmlT Identity () -> HtmlT Identity ()
forall arg result. Term arg result => arg -> result
a_ [Class -> Attributes
cssClass_ Class
Class.AnchorLink, Text -> Attributes
href_ ([Char] -> Text
pack [Char]
path Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"#" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Label -> Text
unLabel Label
label)]
exportLink :: FilePath -> LabelWrapper
exportLink :: [Char] -> LabelWrapper
exportLink [Char]
path Label
label =
HtmlT Identity () -> HtmlT Identity ()
forall arg result. Term arg result => arg -> result
div_
(HtmlT Identity () -> HtmlT Identity ())
-> (HtmlT Identity () -> HtmlT Identity ())
-> HtmlT Identity ()
-> HtmlT Identity ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Attributes] -> HtmlT Identity () -> HtmlT Identity ()
forall arg result. Term arg result => arg -> result
a_ [Class -> Attributes
cssClass_ Class
Class.AnchorLink, Text -> Attributes
href_ ([Char] -> Label -> Text
labelPath [Char]
path Label
label)]
(HtmlT Identity () -> HtmlT Identity ())
-> (HtmlT Identity () -> HtmlT Identity ())
-> HtmlT Identity ()
-> HtmlT Identity ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([Attributes] -> HtmlT Identity () -> HtmlT Identity ()
forall arg result. Term arg result => arg -> result
span_ ([Attributes] -> HtmlT Identity () -> HtmlT Identity ())
-> Class -> HtmlT Identity () -> HtmlT Identity ()
forall a. ([Attributes] -> a) -> Class -> a
<#> Class
Class.LargeFontSize (HtmlT Identity () -> HtmlT Identity ())
-> HtmlT Identity () -> HtmlT Identity ()
forall a b. (a -> b) -> a -> b
$ Text -> HtmlT Identity ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
forall (m :: * -> *). Monad m => Text -> HtmlT m ()
toHtml (Text
"↗ " :: Text)) HtmlT Identity () -> HtmlT Identity () -> HtmlT Identity ()
forall a. Semigroup a => a -> a -> a
<>)
labelPath :: FilePath -> Label -> Text
labelPath :: [Char] -> Label -> Text
labelPath [Char]
path Label
label = [Char] -> Text
pack [Char]
path Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"/" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Label -> Text
unLabel Label
label Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
".html"
collectExportSection
:: Text -> Delayed Text -> Delayed (Html ()) -> ReaderStateMonad ()
collectExportSection :: Text
-> Delayed Text
-> Delayed (HtmlT Identity ())
-> ReaderT ReaderState (State GlobalState) ()
collectExportSection Text
htmlId Delayed Text
title Delayed (HtmlT Identity ())
sectionHtml =
(GlobalState -> GlobalState)
-> ReaderT ReaderState (State GlobalState) ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify
(\GlobalState
s -> GlobalState
s {exportSections = (htmlId, title, sectionHtml) : exportSections s})
setHasErrors :: ReaderStateMonad ()
setHasErrors :: ReaderT ReaderState (State GlobalState) ()
setHasErrors = (GlobalState -> GlobalState)
-> ReaderT ReaderState (State GlobalState) ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify (\GlobalState
s -> GlobalState
s {hasErrors = True})
data Delayed a = Now a | Later (GlobalState -> a)
evalDelayed :: GlobalState -> Delayed a -> a
evalDelayed :: forall a. GlobalState -> Delayed a -> a
evalDelayed GlobalState
_ (Now a
a) = a
a
evalDelayed GlobalState
s (Later GlobalState -> a
fa) = GlobalState -> a
fa GlobalState
s
returnNow :: a -> ReaderStateMonad (Delayed a)
returnNow :: forall a. a -> ReaderStateMonad (Delayed a)
returnNow = Delayed a -> ReaderT ReaderState (State GlobalState) (Delayed a)
forall a. a -> ReaderT ReaderState (State GlobalState) a
forall (m :: * -> *) a. Monad m => a -> m a
return (Delayed a -> ReaderT ReaderState (State GlobalState) (Delayed a))
-> (a -> Delayed a)
-> a
-> ReaderT ReaderState (State GlobalState) (Delayed a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Delayed a
forall a. a -> Delayed a
Now
instance (Monoid a) => Monoid (Delayed a) where
mempty :: Delayed a
mempty = a -> Delayed a
forall a. a -> Delayed a
Now a
forall a. Monoid a => a
mempty
instance (Semigroup a) => Semigroup (Delayed a) where
Now a
a <> :: Delayed a -> Delayed a -> Delayed a
<> Now a
b = a -> Delayed a
forall a. a -> Delayed a
Now (a
a a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
b)
Now a
a <> Later GlobalState -> a
fb = (GlobalState -> a) -> Delayed a
forall a. (GlobalState -> a) -> Delayed a
Later (\GlobalState
s -> a
a a -> a -> a
forall a. Semigroup a => a -> a -> a
<> GlobalState -> a
fb GlobalState
s)
Later GlobalState -> a
fa <> Now a
b = (GlobalState -> a) -> Delayed a
forall a. (GlobalState -> a) -> Delayed a
Later (\GlobalState
s -> GlobalState -> a
fa GlobalState
s a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
b)
Later GlobalState -> a
fa <> Later GlobalState -> a
fb = (GlobalState -> a) -> Delayed a
forall a. (GlobalState -> a) -> Delayed a
Later (\GlobalState
s -> GlobalState -> a
fa GlobalState
s a -> a -> a
forall a. Semigroup a => a -> a -> a
<> GlobalState -> a
fb GlobalState
s)
instance Functor Delayed where
fmap :: forall a b. (a -> b) -> Delayed a -> Delayed b
fmap a -> b
f (Now a
a) = b -> Delayed b
forall a. a -> Delayed a
Now (b -> Delayed b) -> b -> Delayed b
forall a b. (a -> b) -> a -> b
$ a -> b
f a
a
fmap a -> b
f (Later GlobalState -> a
fa) = (GlobalState -> b) -> Delayed b
forall a. (GlobalState -> a) -> Delayed a
Later (a -> b
f (a -> b) -> (GlobalState -> a) -> GlobalState -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GlobalState -> a
fa)
instance Applicative Delayed where
pure :: forall a. a -> Delayed a
pure = a -> Delayed a
forall a. a -> Delayed a
Now
Now a -> b
fa <*> :: forall a b. Delayed (a -> b) -> Delayed a -> Delayed b
<*> Now a
a = b -> Delayed b
forall a. a -> Delayed a
Now (a -> b
fa a
a)
Now a -> b
fa <*> Later GlobalState -> a
fsa = (GlobalState -> b) -> Delayed b
forall a. (GlobalState -> a) -> Delayed a
Later (a -> b
fa (a -> b) -> (GlobalState -> a) -> GlobalState -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GlobalState -> a
fsa)
Later GlobalState -> a -> b
fsfa <*> Now a
a = (GlobalState -> b) -> Delayed b
forall a. (GlobalState -> a) -> Delayed a
Later (\GlobalState
s -> GlobalState -> a -> b
fsfa GlobalState
s a
a)
Later GlobalState -> a -> b
fsfa <*> Later GlobalState -> a
fsa = (GlobalState -> b) -> Delayed b
forall a. (GlobalState -> a) -> Delayed a
Later (\GlobalState
s -> GlobalState -> a -> b
fsfa GlobalState
s (GlobalState -> a
fsa GlobalState
s))
instance Monad Delayed where
return :: forall a. a -> Delayed a
return = a -> Delayed a
forall a. a -> Delayed a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
Now a
a >>= :: forall a b. Delayed a -> (a -> Delayed b) -> Delayed b
>>= a -> Delayed b
fa = a -> Delayed b
fa a
a
Later GlobalState -> a
fsa >>= a -> Delayed b
fa =
(GlobalState -> b) -> Delayed b
forall a. (GlobalState -> a) -> Delayed a
Later
( \GlobalState
s -> case a -> Delayed b
fa (a -> Delayed b) -> a -> Delayed b
forall a b. (a -> b) -> a -> b
$ GlobalState -> a
fsa GlobalState
s of
Now b
b -> b
b
Later GlobalState -> b
fsb -> GlobalState -> b
fsb GlobalState
s
)