support updates
This commit is contained in:
parent
e296e41b8b
commit
7f91331195
7 changed files with 120 additions and 39 deletions
|
@ -131,22 +131,27 @@ makeYearItems nsfw year infos = [b|@4
|
|||
year' = show year & foldMap \c -> [b|<span class=y>$c</span>|]
|
||||
|
||||
makeItem :: Bool -> FilePath -> Info -> Builder
|
||||
makeItem nsfw file info@(Info {title, bg, date}) = [b|@4
|
||||
<li class="item post$nsfw'" data-tags="$tags'" data-date="$date'">
|
||||
makeItem nsfw file info@(Info {title, bg}) = [b|@4
|
||||
<li class="item post$nsfw'" data-date="$date'" data-updated="$updated'"
|
||||
data-tags="$tags'">
|
||||
<figure>
|
||||
<a href="$dir">
|
||||
<img src="$thumb"$bgStyle>
|
||||
</a>
|
||||
<figcaption>$title</figcaption>
|
||||
<figcaption>
|
||||
<span class=date>$date'</span>
|
||||
<span class=title>$title</span>
|
||||
</figcaption>
|
||||
</figure>
|
||||
|]
|
||||
where
|
||||
dir = takeDirectory file
|
||||
thumb = getThumb dir info
|
||||
nsfw' = if nsfw && #anyNsfw info then [b| nsfw|] else ""
|
||||
tags' = fold $ intersperse ";" $ map fromText $ tagsFor nsfw info
|
||||
date' = formatDateShort date
|
||||
bgStyle = ifJust bg \col -> [b| style="background: $col"|]
|
||||
dir = takeDirectory file
|
||||
thumb = getThumb dir info
|
||||
nsfw' = if nsfw && #anyNsfw info then [b| nsfw|] else ""
|
||||
tags' = fold $ intersperse ";" $ map fromText $ tagsFor nsfw info
|
||||
date' = formatDateShort $ #latestDate info
|
||||
updated' = if #updated info then [b|true|] else [b|false|]
|
||||
bgStyle = ifJust bg \col -> [b| style="background: $col"|]
|
||||
|
||||
formatDateShort :: Time.Day -> Builder
|
||||
formatDateShort date = [b|$day $month|] where
|
||||
|
|
|
@ -19,6 +19,7 @@ import Data.Foldable (find)
|
|||
import Data.Hashable (Hashable)
|
||||
import Data.HashSet (HashSet)
|
||||
import qualified Data.HashSet as HashSet
|
||||
import Data.Map.Strict (Map)
|
||||
import qualified Data.Map.Strict as Map
|
||||
import Data.Maybe (isJust, isNothing)
|
||||
import Data.List (nub)
|
||||
|
@ -40,6 +41,7 @@ data Info =
|
|||
-- e.g. multiple things on the same day might have a,b,c in @sortEx@ to
|
||||
-- put them in the right order in the gallery
|
||||
sortEx :: !Text,
|
||||
updates :: !(Map Day Text),
|
||||
title :: !Text,
|
||||
artist :: !(Maybe Artist), -- nothing = me, obv
|
||||
nsfwOnly :: !Bool,
|
||||
|
@ -109,6 +111,11 @@ instance HasField "year" Info Integer where getField = #first . #dmy
|
|||
instance HasField "month" Info Int where getField = #second . #dmy
|
||||
instance HasField "day" Info Int where getField = #third . #dmy
|
||||
|
||||
instance HasField "latestDate" Info Day where
|
||||
getField (Info {date, updates}) = maximum (date : Map.keys updates)
|
||||
|
||||
instance HasField "updated" Info Bool where getField = not . Map.null . #updates
|
||||
|
||||
descFor :: Bool -> Info -> Maybe Text
|
||||
descFor nsfw (Info {desc, nsfwDesc}) = desc <> (guard nsfw *> nsfwDesc)
|
||||
|
||||
|
@ -122,7 +129,7 @@ linksFor :: Bool -> Info -> [Link]
|
|||
linksFor nsfw = if nsfw then #links else #sfwLinks
|
||||
|
||||
instance Ord Info where
|
||||
compare = comparing \Info {date, sortEx, title} -> (date, sortEx, title)
|
||||
compare = comparing \i -> (#latestDate i, #sortEx i, #title i)
|
||||
|
||||
|
||||
newtype NoThumb = NoThumb FilePath
|
||||
|
@ -150,7 +157,8 @@ addSuffix suf path =
|
|||
instance FromYAML Info where
|
||||
parseYAML = YAML.withMap "info" \m ->
|
||||
Info <$> m .: "date"
|
||||
<*> m .:? "sort" .!= ""
|
||||
<*> m .:? "sort" .!= ""
|
||||
<*> m .:? "updates" .!= []
|
||||
<*> m .: "title"
|
||||
<*> m .:? "artist"
|
||||
<*> m .:? "nsfw-only" .!= False
|
||||
|
|
|
@ -5,10 +5,11 @@ import BuilderQQ
|
|||
import Records ()
|
||||
|
||||
import Control.Exception
|
||||
import qualified Data.Map.Strict as Map
|
||||
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 qualified Data.Time as Time
|
||||
import System.FilePath (joinPath, splitPath, (</>))
|
||||
import qualified System.Process as Proc
|
||||
import Text.Read (readMaybe)
|
||||
|
@ -34,7 +35,8 @@ make root prefix nsfw dataDir dir info =
|
|||
toLazyText <$> make' root prefix nsfw dataDir dir info
|
||||
|
||||
make' :: Text -> FilePath -> Bool -> FilePath -> FilePath -> Info -> IO Builder
|
||||
make' root prefix nsfw dataDir dir info@(Info {date, title, artist, bg}) = do
|
||||
make' root prefix nsfw dataDir dir
|
||||
info@(Info {date, title, artist, bg, updates}) = do
|
||||
images <- withSizes (dataDir </> dir) $ imagesFor nsfw info
|
||||
|
||||
let undir = joinPath (replicate (length (splitPath dir)) "..")
|
||||
|
@ -53,6 +55,7 @@ make' root prefix nsfw dataDir dir info@(Info {date, title, artist, bg}) = do
|
|||
let descSection = makeDesc $ descFor nsfw info
|
||||
let tagsList = makeTags undir $ tagsFor nsfw info
|
||||
let linksList = extLinks $ linksFor nsfw info
|
||||
let updatesList = makeUpdates $ Map.toList updates
|
||||
|
||||
let makePrefetch (Image {path}) = [b|<link rel=prefetch href=$path>|]
|
||||
let prefetches = map (makePrefetch . #first) $ tail images
|
||||
|
@ -76,6 +79,9 @@ make' root prefix nsfw dataDir dir info@(Info {date, title, artist, bg}) = do
|
|||
Nothing -> "by niss"
|
||||
let thumb = getThumb "" info
|
||||
|
||||
let updateDate = ifJust (Map.lookupMax updates) \(formatDate -> u, _) ->
|
||||
[b|<br> <span class=updated>updated $u</span>|]
|
||||
|
||||
pure [b|@0
|
||||
<!DOCTYPE html>
|
||||
<html lang=en>
|
||||
|
@ -103,7 +109,9 @@ make' root prefix nsfw dataDir dir info@(Info {date, title, artist, bg}) = do
|
|||
<header>
|
||||
<h1>$title</h1>
|
||||
$artistTag
|
||||
<h2 id=date class="right corner">$formattedDate</h2>
|
||||
<h2 id=date class="right corner">
|
||||
$formattedDate $updateDate
|
||||
</h2>
|
||||
</header>
|
||||
|
||||
$buttonBar
|
||||
|
@ -122,6 +130,8 @@ make' root prefix nsfw dataDir dir info@(Info {date, title, artist, bg}) = do
|
|||
$tagsList
|
||||
|
||||
$linksList
|
||||
|
||||
$updatesList
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|
@ -217,6 +227,25 @@ extLink (Link {title, url}) = [b|@8
|
|||
</a>
|
||||
|]
|
||||
|
||||
makeUpdates :: [(Day, Text)] -> Builder
|
||||
makeUpdates ups =
|
||||
if null ups then "" else [b|@4
|
||||
<section id=updates class=info-section>
|
||||
<h2>updates</h2>
|
||||
<dl>
|
||||
$8.updateList
|
||||
</dl>
|
||||
</section>
|
||||
|]
|
||||
where updateList = map (uncurry makeUpdate) ups
|
||||
|
||||
makeUpdate :: Day -> Text -> Builder
|
||||
makeUpdate date txt = [b|@8
|
||||
<dt>$date'
|
||||
<dd>$txt
|
||||
|]
|
||||
where date' = Time.formatTime Time.defaultTimeLocale "%-d/%-m/%Y" date
|
||||
|
||||
formatDate :: Day -> Builder
|
||||
formatDate date = [b|$week $day $month $year|] where
|
||||
(year, month', day') = Time.toGregorian date
|
||||
|
|
1
style/cake.svg
Normal file
1
style/cake.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="1.5" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><metadata/><path d="m0 0h32v32h-32z" fill="none"/><path d="m15.086 6.532c.129-.53.401-1.019.793-1.411l1-1c.562-.562 1.325-.878 2.121-.878s1.559.316 2.121.878c.251.251.507.507.758.758.268.268.48.581.628.922 2.498.742 4.839 1.987 6.87 3.68.384.32.623.519.623.519v13l-28 7v-13z" fill="none" stroke="#000" stroke-width="4"/><path d="m2 19v-2l2-1 23-7 3 1v13l-2 .5z" fill="#ccc"/><path d="m28 18.5v5l-26 6.5v-5l1-1 24-6zm-26 4.5v-4l24.757-6.189c.299-.075.616-.008.858.182.243.189.385.48.385.788v2.719l-1 1.5-24 5.5-1-.5z" fill="#eaae53"/><path d="m28 18.5-26 6.5v-2l26-6.5z" fill="#da6363"/><path d="m2 17 15-12c4.523 0 8.903 1.586 12.377 4.481.384.32.623.519.623.519l-28 7z" fill="#fff"/><path d="m16 11c-.265 0-.52-.105-.707-.293-.188-.187-.293-.442-.293-.707v-2.757c0-.796.316-1.559.879-2.122l1-1c.562-.562 1.325-.878 2.121-.878s1.559.316 2.121.878c.251.251.507.507.758.758.562.562.878 1.325.878 2.121s-.316 1.559-.878 2.121c-.353.353-.702.702-1 1-.563.563-1.326.879-2.122.879-.85 0-1.964 0-2.757 0z" fill="#d72d35"/></svg>
|
After Width: | Height: | Size: 1.2 KiB |
|
@ -116,17 +116,12 @@ body {
|
|||
box-shadow: var(--focus-box);
|
||||
}
|
||||
|
||||
.item[data-date]::before {
|
||||
content: attr(data-date);
|
||||
}
|
||||
|
||||
|
||||
figure {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
figcaption, .item::before {
|
||||
figcaption .date, figcaption .title {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
border: 1px solid var(--text-col);
|
||||
|
@ -134,10 +129,11 @@ figcaption, .item::before {
|
|||
text-align: center;
|
||||
background: hsl(0, 0%, 0%, 75%);
|
||||
font-size: 80%;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
figcaption { bottom: -1px; left: -1px; }
|
||||
.item::before { top: -1px; left: -1px; }
|
||||
figcaption .date { top: -1px; left: -1px; }
|
||||
figcaption .title { bottom: -1px; left: -1px; }
|
||||
|
||||
.year-marker {
|
||||
grid-area: auto / 1;
|
||||
|
@ -164,19 +160,31 @@ figcaption { bottom: -1px; left: -1px; }
|
|||
transform: scaleX(110%);
|
||||
}
|
||||
|
||||
.item.nsfw::after {
|
||||
--size: calc(1/4 * var(--image-size));
|
||||
content: url(../18_plus_white.svg);
|
||||
.item.nsfw::before, .item[data-updated="true"]::after {
|
||||
height: var(--size);
|
||||
width: var(--size);
|
||||
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
|
||||
}
|
||||
|
||||
.item.nsfw::before {
|
||||
--size: calc(1/4 * var(--image-size));
|
||||
--base-transform: rotate(var(--nsfw-sticker-rotate));
|
||||
content: url(../18_plus_white.svg);
|
||||
top: calc(1em + 3px);
|
||||
right: 3px;
|
||||
|
||||
transform: rotate(var(--nsfw-sticker-rotate));
|
||||
mix-blend-mode: multiply;
|
||||
transform: var(--base-transform);
|
||||
}
|
||||
|
||||
.item[data-updated="true"]::after {
|
||||
--size: calc(1/4 * var(--image-size));
|
||||
content: url(../sparkles.svg);
|
||||
bottom: calc(1em + 3px);
|
||||
right: 3px;
|
||||
mix-blend-mode: overlay;
|
||||
}
|
||||
|
||||
footer {
|
||||
|
@ -187,30 +195,33 @@ footer {
|
|||
|
||||
|
||||
@media (hover) {
|
||||
.item:hover figcaption, .item:hover::before {
|
||||
.item:hover .date, .item:hover .title,
|
||||
.item:hover::before, .item:hover::after {
|
||||
filter: opacity(20%);
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion) {
|
||||
.item:hover figcaption {
|
||||
transform: translateY(80%);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
figcaption, .item::before {
|
||||
figcaption .date, figcaption .title, .item::before, .item::after {
|
||||
transition-property: filter, transform;
|
||||
transition-duration: 0.25s;
|
||||
transition-duration: 0.15s;
|
||||
transition-timing-function: ease-in-out;
|
||||
}
|
||||
|
||||
.item:hover figcaption {
|
||||
.item:hover .title {
|
||||
transform: translate(-20%, 80%) rotateZ(7deg);
|
||||
}
|
||||
|
||||
.item:hover::before {
|
||||
.item:hover .date {
|
||||
transform: translate(20%, -80%) rotateZ(7deg);
|
||||
}
|
||||
|
||||
.item:hover::before {
|
||||
transform: translate(1.5em, -1.5em) var(--base-transform);
|
||||
}
|
||||
|
||||
.item:hover::after {
|
||||
transform: translate(1.5em, 1.5em);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,10 +230,14 @@ footer {
|
|||
height: min-content;
|
||||
}
|
||||
|
||||
figcaption {
|
||||
figcaption .date, figcaption .title {
|
||||
position: initial;
|
||||
}
|
||||
|
||||
figcaption .date::after {
|
||||
content: ':';
|
||||
}
|
||||
|
||||
.item a {
|
||||
display: block;
|
||||
height: var(--image-size);
|
||||
|
|
|
@ -132,6 +132,28 @@ body {
|
|||
margin: 0.35em;
|
||||
}
|
||||
|
||||
#updates dl {
|
||||
display: grid;
|
||||
grid-template-columns: min-content auto;
|
||||
grid-gap: 0.5em;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
#updates dt {
|
||||
font-size: 80%;
|
||||
font-weight: 700;
|
||||
grid-area: auto / 1;
|
||||
}
|
||||
|
||||
#updates dd {
|
||||
grid-area: auto / 2;
|
||||
}
|
||||
|
||||
.updated {
|
||||
font-size: 90%;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
footer {
|
||||
text-align: center;
|
||||
margin-top: 1em;
|
||||
|
|
1
style/sparkles.svg
Normal file
1
style/sparkles.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="1.5" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><metadata/><g fill="none"><path d="m0 0h32v32h-32z"/><path d="m14 15 5.5-2.5 2.5-8.5 2.5 8.5 5.5 2.5-5.5 2.5-2.5 8.5-2.5-8.5z" stroke="#000" stroke-width="4"/><path d="m4 23 3.5-1.5 1.5-5.5 1.5 5.5 3.5 1.5-3.5 1.5-1.5 5.5-1.5-5.5z" stroke="#000" stroke-width="4"/><path d="m2 7 2-1 1-4 1 4 2 1-2 1-1 4-1-4z" stroke="#000" stroke-width="4"/></g><path d="m14 15 5.5-2.5 2.5-8.5 2.5 8.5 5.5 2.5-5.5 2.5-2.5 8.5-2.5-8.5z" fill="#fdef24"/><path d="m4 23 3.5-1.5 1.5-5.5 1.5 5.5 3.5 1.5-3.5 1.5-1.5 5.5-1.5-5.5z" fill="#fdef24"/><path d="m2 7 2-1 1-4 1 4 2 1-2 1-1 4-1-4z" fill="#fdef24"/></svg>
|
After Width: | Height: | Size: 760 B |
Loading…
Reference in a new issue