hablo/src/DOM.hs

139 lines
4.7 KiB
Haskell
Raw Normal View History

2019-01-27 21:41:21 +01:00
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
module DOM (
PageType(..)
, htmlDocument
2019-01-27 21:41:21 +01:00
) where
import Article (Article)
2019-02-15 14:13:43 +01:00
import qualified Article (preview)
import ArticlesList (
ArticlesList(..), description, getArticles, otherURL, rssLinkTexts
)
import Blog (Blog(..), Skin(..), URLs(..), template)
import Blog.URL (localPrefix)
import qualified Collection (tag)
import Control.Monad.Reader (ReaderT, asks)
import Data.Map as Map (Map, toList)
import Data.Text (Text, pack, empty)
import DOM.Card (HasCard)
import qualified DOM.Card as Card (make)
2021-07-01 09:01:08 +02:00
--import Lucid (
-- Attribute, HtmlT, a_, article_, body_, charset_, class_, div_, doctypehtml_
-- , h1_, h2_, head_, header_, href_, li_, link_, id_, meta_, pre_, rel_
-- , script_, src_, title_, toHtml, toHtmlRaw, type_, ul_
-- )
import Markdown (Markdown(..), MarkdownContent(..))
import Network.URL (URL)
import Page (Page)
2021-07-01 09:01:08 +02:00
import Prelude hiding (div, head, id, lookup)
import Pretty ((.$))
import System.FilePath.Posix ((</>), (<.>))
2021-07-01 09:01:08 +02:00
import Text.Blaze.Html5 as H (
(!), Html, ToValue(..), body, div, docTypeHtml, h2, head, li, meta, preEscapedText, script, text, title, ul
)
import Text.Blaze.Html5.Attributes (
charset, class_, id, src
)
2021-07-01 09:01:08 +02:00
type HtmlGenerator = ReaderT Blog IO Html
2019-01-27 21:41:21 +01:00
class HasCard a => PageType a where
2021-07-01 09:01:08 +02:00
content :: a -> HtmlGenerator
pathToRoot :: a -> FilePath
instance PageType Article where
content = mDContent True ".." . getMarkdown
pathToRoot _ = ".."
instance PageType Page where
content = mDContent True ".." . getMarkdown
pathToRoot _ = ".."
instance PageType ArticlesList where
content al@(ArticlesList {full}) = do
preview <- Article.preview <$> (asks $skin.$previewLinesCount)
2021-07-01 09:01:08 +02:00
h2_ . text =<< description al
ul_ $ do
asks hasRSS >>= rssLink
li_ . a_ [href_ . pack $ otherURL al, class_ "other"] =<< otherLink
2021-07-01 09:01:08 +02:00
div [class_ "articles"] (
mapM_ (mDContent False (pathToRoot al) . preview) =<< getArticles al
2019-02-15 14:13:43 +01:00
)
2019-02-17 19:52:28 +01:00
where
otherLink =
toHtml <$> template (if full then "latestLink" else "allLink") []
2021-07-01 09:01:08 +02:00
rssLink :: Bool -> HtmlGenerator
rssLink True = do
(text, title) <- rssLinkTexts al
li_ . a_ [href_ "rss.xml", class_ "RSS", title_ title] $ toHtml text
rssLink False = return ()
2019-02-15 14:13:43 +01:00
pathToRoot = maybe "." (\_ -> "..") . Collection.tag . collection
2021-07-01 09:01:08 +02:00
mDContent :: Bool -> FilePath -> Markdown -> HtmlGenerator
mDContent raw base markdown@(Markdown {key, Markdown.body}) =
article_ ! id (toValue key) (do
header_ . h1_ $ mDLink raw base markdown
2019-02-15 14:13:43 +01:00
pre_ . toHtml $ unlines body
)
2021-07-01 09:01:08 +02:00
mDLink :: Bool -> FilePath -> Markdown -> HtmlGenerator
mDLink raw base (Markdown {Markdown.path, Markdown.title}) = link $ toHtml title
where
link = a_ [href_ . prefix base $ path <.> (if raw then "md" else "html")]
prefix :: FilePath -> FilePath -> Text
prefix base = pack . (base </>)
2021-07-01 09:01:08 +02:00
tag :: FilePath -> String -> HtmlGenerator
tag base name =
a_ [href_ . prefix base $ name ++ "/", class_ "tag"] $ toHtml name
2021-07-01 09:01:08 +02:00
defaultBanner :: FilePath -> HtmlGenerator
defaultBanner base =
2021-07-01 09:01:08 +02:00
div ! id "header" $
a_ [href_ $ pack base] (
h1_ . toHtml =<< asks name
)
2019-01-27 21:41:21 +01:00
2021-07-01 09:01:08 +02:00
faviconLink :: FilePath -> URL -> HtmlGenerator
faviconLink base url = link_ [
rel_ "shortcut icon", href_ $ localPrefix base url, type_ "image/x-icon"
]
2021-07-01 09:01:08 +02:00
optional :: (a -> HtmlGenerator) -> Maybe a -> HtmlGenerator
optional = maybe (return mempty)
navigationSection ::
2021-07-01 09:01:08 +02:00
Text -> String -> ((String, a) -> HtmlGenerator) -> Map String a -> HtmlGenerator
navigationSection sectionId templateKey generator collection
| null collection = return ()
| otherwise =
2021-07-01 09:01:08 +02:00
div ! id sectionId ! class_ "navigator" $ do
h2 . toHtml =<< template templateKey []
ul $ (li . generator) <$> Map.toList collection
2021-07-01 09:01:08 +02:00
htmlDocument :: PageType a => a -> HtmlGenerator
htmlDocument someContent =
let base = pathToRoot someContent in
2021-07-01 09:01:08 +02:00
docTypeHtml (do
H.head (do
meta ! charset "utf-8"
H.title . text =<< asks name
script ! src (prefix base "js/remarkable.min.js") mempty
script ! src (prefix base "js/hablo.js") mempty
optional (faviconLink base) =<< (asks $skin.$favicon)
optional (Card.make someContent) =<< (asks $urls.$cards)
2021-07-01 09:01:08 +02:00
optional preEscapedText =<< (asks $skin.$Blog.head)
2019-01-27 21:41:21 +01:00
)
2021-07-01 09:01:08 +02:00
H.body (do
maybe (defaultBanner base) preEscapedText =<< (asks $skin.$banner)
asks tags >>= navigationSection "tags" "tagsList"
(\(key, _) -> tag base key)
asks pages >>= navigationSection "pages" "pagesList"
(\(_, page) -> mDLink False base $ getMarkdown page)
2021-07-01 09:01:08 +02:00
div ! id "contents" $ content someContent
2019-01-27 21:41:21 +01:00
)
)