module SinglePage (make) where
import Depend (pageFile)
import Info hiding (Text)
import BuilderQQ
import Records ()
import Control.Exception
import Data.Maybe (fromMaybe)
import qualified Data.Text as Strict
import qualified Data.Text.Lazy as Lazy
import qualified Data.Time.Calendar as Time
import System.FilePath (joinPath, splitPath)
-- | 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 -> FilePath -> Info -> Lazy.Text
make nsfw dir = toLazyText . make' nsfw dir
make' :: Bool -> FilePath -> Info -> Builder
make' nsfw dir info@(Info {date, title, artist}) = [b|@0
$0.prefetches
$*title
$*title
$artistTag
$formattedDate
$buttonBar
$descSection
$tagsList
$linksList
|]
where
artistTag = ifJust artist makeArtist
formattedDate = formatDate date
buttonBar = makeButtonBar title images
image0 = head images
path0 = #path image0
download0 = fromMaybe path0 (#download image0)
path0' = pageFile path0
images = imagesFor nsfw info
descSection = makeDesc $ descFor nsfw info
tagsList = makeTags undir $ tagsFor nsfw info
linksList = extLinks $ linksFor nsfw info
prefetches = map makePrefetch $ tail images
makePrefetch (Image {path}) = [b||]
warning' = ifJust (#warning image0) \w -> [b|@4
cw: $*w
|]
undir = joinPath (replicate (length (splitPath dir)) "..")
makeArtist :: Artist -> Builder
makeArtist (Artist {name, url}) =
[b|
by $artistLink
|]
where
artistLink = case url of
Just u -> [b|$*name|]
Nothing -> [b|$*name|]
makeDesc :: Strict.Text -> Builder
makeDesc desc = [b|@4
about
$8*desc
|]
makeButtonBar :: Strict.Text -> [Image] -> Builder
makeButtonBar title images =
case length images of
0 -> throw $ NoEligibleImages title
1 -> ""
_ -> [b|@0
|]
where alts = map (uncurry altButton) $ zip [0..] images
altButton :: Int -> Image -> Builder
altButton i (Image {label, path, nsfw, warning}) = [b|@4
|]
where
nsfwClass = if nsfw then " class=nsfw" else ""
nsfwLabelClass = if nsfw then " class=nsfw-label" else ""
checked = if i == 0 then " checked" else ""
idLabel = escId label
path' = pageFile path
warning' = ifJust warning \w -> [b| data-warning="$*w"|]
makeTags :: FilePath -> [Strict.Text] -> Builder
makeTags undir tags =
if null tags then "" else [b|@4
|]
where
tagList = map makeTag tags
makeTag tag = [b|
$*tag|]
where tag' = escId tag
extLinks :: [Link] -> Builder
extLinks links =
if null links then "" else [b|@4
|]
where linkList = map extLink links
extLink :: Link -> Builder
extLink (Link {title, url}) = [b|@8
$*title
|]
formatDate :: Day -> Builder
formatDate date = [b|$*week $day $*month $^year|] where
(year, month', day') = Time.toGregorian date
week' = Time.dayOfWeek date
day = nth day'
month = Strict.words "january february march april may june july \
\august september october november december"
!! (month' - 1)
week = Strict.words "mon tue wed thu fri sat sun" !! (fromEnum week' - 1)
nth :: Int -> Builder
nth n = [b|$^n$suf|] where
suf | n >= 10, n <= 19 = "th"
| n `mod` 10 == 1 = "st"
| n `mod` 10 == 2 = "nd"
| n `mod` 10 == 3 = "rd"
| otherwise = "th"