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 -- | e.g. 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

tags

|] 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 |]