module SinglePage (make) where
import Info hiding (Text)
import BuildVar
import Control.Exception
import qualified Data.Text as Strict
import qualified Data.Text.Lazy as Lazy
import Data.Text.Lazy.Builder
import Data.Time (formatTime, defaultTimeLocale)
import Data.Maybe (fromMaybe)
import qualified Data.Char as Char
import qualified Data.List as List
-- | only nsfw images are present for a non-nsfw page
data NoEligibleImages = NoEligibleImages {title :: !Strict.Text}
deriving stock Eq deriving anyclass Exception
instance Show NoEligibleImages where
show (NoEligibleImages {title}) =
Strict.unpack title <> ": no images selected\n" <>
" (probably a nsfw-only work without --nsfw set)"
make :: Bool -> Info -> Lazy.Text
make includeNsfw = toLazyText . make' includeNsfw
make' :: Bool -> Info -> Builder
make' includeNsfw (Info {date, title, tags, nsfwTags,
description, images, links}) = [b|@0
$titleTag
$titleHeader
$formattedDate
$buttonBar
$descSection
$tagsList
$linksList
|]
where
titleTag = ifJust title \t -> [b|
$*t|]
titleHeader = ifJust title \t -> [b|$*t
|]
formattedDate = formatDate date
buttonBar = makeButtonBar (fromMaybe path0 title) includeNsfw images
path0 = let Image {path} = head images in path
descSection = ifJust description makeDesc
tagsList = makeTags includeNsfw tags nsfwTags
linksList = extLinks includeNsfw links
makeDesc :: Strict.Text -> Builder
makeDesc desc = [b|@2
description
$4*desc
|]
ifJust :: Monoid b => Maybe a -> (a -> b) -> b
ifJust x f = maybe mempty f x
formatDate :: Day -> Builder
formatDate = fromString . formatTime defaultTimeLocale "%e %#B %Y"
makeButtonBar :: Strict.Text -> Bool -> [Image] -> Builder
makeButtonBar title includeNsfw allImages =
case length images of
0 -> throw $ NoEligibleImages title
1 -> ""
_ -> [b|@2
|]
where
images | includeNsfw = allImages
| otherwise = filter (\Image {nsfw} -> not nsfw) allImages
iimages = zip [0..] images
alts = map (uncurry altButton) iimages
altButton :: Int -> Image -> Builder
altButton i (Image {label, path, nsfw}) = [b|@6
|]
where
nsfwClass = if nsfw then " class=nsfw" else ""
checked = if i == 0 then " checked" else ""
idLabel = escId label
escId :: Strict.Text -> Builder
escId = foldMap esc1 . Strict.unpack where
esc1 c
| Char.isSpace c = ""
| c < 'ΓΏ' && not (Char.isAlphaNum c || c == '-') = "_"
| otherwise = singleton c
makeTags :: Bool -> [Strict.Text] -> [Strict.Text] -> Builder
makeTags includeNsfw sfwTags nsfwTags =
if null tags then "" else [b|@2
|]
where
tagList = map makeTag tags
makeTag t = [b|$*t|]
tags = List.nub $ if includeNsfw then sfwTags else sfwTags <> nsfwTags
extLinks :: Bool -> [Link] -> Builder
extLinks includeNsfw allLinks =
if null links then "" else [b|@2
|]
where
links | includeNsfw = allLinks
| otherwise = filter (\Link {nsfw} -> not nsfw) allLinks
linkList = map extLink links
extLink :: Link -> Builder
extLink (Link {title, url}) = [b|@6
$*title
|]