gallery/make-pages/GalleryPage.hs

155 lines
4.5 KiB
Haskell
Raw Normal View History

2020-07-19 11:55:54 -04:00
{-# LANGUAGE TransformListComp #-}
2020-07-16 10:07:28 -04:00
module GalleryPage (make) where
2020-09-25 17:08:44 -04:00
import BuilderQQ
import Date
import Info
2020-08-03 17:07:59 -04:00
import Data.Foldable
2020-07-20 16:40:34 -04:00
import Data.Function (on, (&))
2020-08-03 17:07:59 -04:00
import qualified Data.HashMap.Strict as HashMap
2020-08-03 20:27:19 -04:00
import Data.HashSet (HashSet)
import qualified Data.HashSet as HashSet
2020-08-03 17:07:59 -04:00
import Data.List (intersperse, groupBy, sortOn)
2020-07-16 10:07:28 -04:00
import qualified Data.Text.Lazy as Lazy
2020-08-11 14:29:54 -04:00
import System.FilePath (takeDirectory, joinPath, splitPath)
2020-07-19 11:55:54 -04:00
import GHC.Exts (Down (..), the)
2020-07-16 10:07:28 -04:00
2020-08-11 14:29:54 -04:00
make :: Text -> GalleryInfo -> [(FilePath, Info)] -> Lazy.Text
make root ginfo infos = toLazyText $ make' root ginfo infos
2020-07-16 10:07:28 -04:00
2020-08-11 14:29:54 -04:00
make' :: Text -> GalleryInfo -> [(FilePath, Info)] -> Builder
make' root (GalleryInfo {title, desc, prefix, filters, hidden}) infos = [b|@0
2020-07-16 10:07:28 -04:00
<!DOCTYPE html>
<html lang=en>
<meta charset=utf-8>
2020-08-04 17:12:58 -04:00
<link rel=stylesheet href=/style/shiny/gallery.css>
2020-08-04 18:52:56 -04:00
<link rel=icon href=/style/niss.svg>
2020-07-19 12:04:40 -04:00
<link rel=alternate href=rss.xml type=application/rss+xml>
2020-07-16 10:07:28 -04:00
2020-08-11 14:29:54 -04:00
<meta property=og:type content=og:website>
<meta property=og:title content="$title">
<meta property=og:site_name content="$title">
<meta property=og:description content="$desc">
<meta property=og:image content="$url/$imagepath0">
2020-08-11 14:29:54 -04:00
<meta property=og:url content="$url">
2020-09-19 02:13:13 -04:00
<meta name=twitter:site content=@2_gecs>
2020-08-11 14:29:54 -04:00
<meta name=twitter:card content=summary>
2020-08-04 13:14:12 -04:00
<script src=/script/gallery.js></script>
2020-08-03 17:11:15 -04:00
<title>$title</title>
2020-07-16 10:07:28 -04:00
<header>
<h1>$title</h1>
2020-07-19 12:04:40 -04:00
<h2 class="right corner">
<a href=rss.xml>rss</a>
</h2>
2020-07-16 10:07:28 -04:00
</header>
2020-08-04 12:22:16 -04:00
<nav id=filters>
<details id=filters-details>
2020-08-03 17:10:52 -04:00
<summary><h2>filters</h2></summary>
<div>
<h3>show only</h3>
<ul id=require class="buttonbar bb-choice">
2020-08-03 17:10:52 -04:00
$8.requireFilters
</ul>
<h3>exclude</h3>
<ul id=exclude class="buttonbar bb-choice">
2020-08-03 17:10:52 -04:00
$8.excludeFilters
</ul>
<a href=# id=clear>clear</a>
<a href=# id=singles>toggle single-use tags</a>
2020-08-03 17:10:52 -04:00
</div>
</details>
2020-08-04 12:22:16 -04:00
</nav>
2020-08-03 17:10:52 -04:00
2020-07-16 10:07:28 -04:00
<main>
<ul class=grid>
$4.items
</ul>
</main>
<footer>
<a href=$undir>all galleries</a>
</footer>
2020-07-16 10:07:28 -04:00
|]
where
2020-07-18 05:43:35 -04:00
items = map (uncurry $ makeYearItems nsfw) infosByYear
2020-07-18 05:43:35 -04:00
infosByYear =
2020-07-19 11:55:54 -04:00
[(the year, infopath) |
infopath@(_, info) <- infos,
then sortOn by Down info,
let year = #latestYear info,
2020-07-19 11:55:54 -04:00
then group by Down year using groupBy']
groupBy' f = groupBy ((==) `on` f)
undir = joinPath (replicate (length (splitPath prefix)) "..")
2020-08-03 17:07:59 -04:00
allTags = infos
& concatMap (map (,1) . tagsFor nsfw . #second)
& HashMap.fromListWith (+) & HashMap.toList
& sortOn (\(tag, count) -> (Down count, tag))
2020-08-03 20:27:19 -04:00
requireFilters = map (uncurry $ makeFilter "require" mempty) allTags
excludeFilters = map (uncurry $ makeFilter "exclude" hidden) allTags
2020-07-18 05:43:35 -04:00
nsfw = #nsfw filters /= NoNsfw
url = [b|$root/$prefix|]
2020-08-11 14:29:54 -04:00
imagepath0
| (_, (p0, i0) : _) : _ <- infosByYear = getThumb (takeDirectory p0) i0
| otherwise = "/style/card.png"
2020-08-03 20:27:19 -04:00
makeFilter :: Text -> HashSet Text -> Text -> Int -> Builder
2020-09-17 13:12:48 -04:00
makeFilter prefix initial tag count = [b|@8
2020-08-03 17:10:52 -04:00
<li>
<input type=checkbox id="$id'" value="$tag"$checked>
2020-09-17 13:12:48 -04:00
<label for="$id'" data-count=$count>$tag</label>
2020-08-03 17:10:52 -04:00
|]
2020-08-03 20:27:19 -04:00
where
id' = [b|$prefix$&_$tag'|]
2020-08-03 20:27:19 -04:00
tag' = escId tag
checked = if HashSet.member tag initial then [b| checked|] else ""
2020-08-03 17:10:52 -04:00
2020-07-18 05:43:35 -04:00
makeYearItems :: Bool -- ^ nsfw
2020-09-25 17:08:44 -04:00
-> Int -- ^ year
2020-07-18 05:43:35 -04:00
-> [(FilePath, Info)]
-> Builder
makeYearItems nsfw year infos = [b|@4
<li class="item year-marker">
2020-07-20 16:40:34 -04:00
<span class=year-text>$year'</span>
2020-07-18 05:43:35 -04:00
$4.items
|]
2020-07-20 16:40:34 -04:00
where
items = map (uncurry $ makeItem nsfw) infos
year' = show year & foldMap \c -> [b|<span class=y>$c</span>|]
2020-07-16 10:07:28 -04:00
makeItem :: Bool -> FilePath -> Info -> Builder
2020-09-19 01:51:52 -04:00
makeItem nsfw file info@(Info {title, bg}) = [b|@4
<li class="item post$nsfw'" data-date="$date'" data-updated="$updated'"
data-tags="$tags'">
2020-07-16 10:07:28 -04:00
<figure>
<a href="$dir">
<img src="$thumb"$bgStyle>
2020-07-16 10:07:28 -04:00
</a>
2020-09-19 01:51:52 -04:00
<figcaption>
<span class=date>$date'</span>
<span class=title>$title</span>
</figcaption>
2020-07-16 10:07:28 -04:00
</figure>
|]
where
2020-09-19 01:51:52 -04:00
dir = takeDirectory file
thumb = getThumb dir info
nsfw' = if nsfw && #anyNsfw info then [b| nsfw|] else ""
tags' = fold $ intersperse ";" $ map fromText $ tagsFor nsfw info
2020-09-25 17:08:44 -04:00
date' = formatShort $ #latestDate info
2020-09-19 01:51:52 -04:00
updated' = if #updated info then [b|true|] else [b|false|]
bgStyle = ifJust bg \col -> [b| style="background: $col"|]