support updates

This commit is contained in:
Rhiannon Morris 2020-09-19 07:51:52 +02:00
parent e296e41b8b
commit 7f91331195
7 changed files with 120 additions and 39 deletions

View File

@ -131,22 +131,27 @@ makeYearItems nsfw year infos = [b|@4
year' = show year & foldMap \c -> [b|<span class=y>$c</span>|] year' = show year & foldMap \c -> [b|<span class=y>$c</span>|]
makeItem :: Bool -> FilePath -> Info -> Builder makeItem :: Bool -> FilePath -> Info -> Builder
makeItem nsfw file info@(Info {title, bg, date}) = [b|@4 makeItem nsfw file info@(Info {title, bg}) = [b|@4
<li class="item post$nsfw'" data-tags="$tags'" data-date="$date'"> <li class="item post$nsfw'" data-date="$date'" data-updated="$updated'"
data-tags="$tags'">
<figure> <figure>
<a href="$dir"> <a href="$dir">
<img src="$thumb"$bgStyle> <img src="$thumb"$bgStyle>
</a> </a>
<figcaption>$title</figcaption> <figcaption>
<span class=date>$date'</span>
<span class=title>$title</span>
</figcaption>
</figure> </figure>
|] |]
where where
dir = takeDirectory file dir = takeDirectory file
thumb = getThumb dir info thumb = getThumb dir info
nsfw' = if nsfw && #anyNsfw info then [b| nsfw|] else "" nsfw' = if nsfw && #anyNsfw info then [b| nsfw|] else ""
tags' = fold $ intersperse ";" $ map fromText $ tagsFor nsfw info tags' = fold $ intersperse ";" $ map fromText $ tagsFor nsfw info
date' = formatDateShort date date' = formatDateShort $ #latestDate info
bgStyle = ifJust bg \col -> [b| style="background: $col"|] updated' = if #updated info then [b|true|] else [b|false|]
bgStyle = ifJust bg \col -> [b| style="background: $col"|]
formatDateShort :: Time.Day -> Builder formatDateShort :: Time.Day -> Builder
formatDateShort date = [b|$day $month|] where formatDateShort date = [b|$day $month|] where

View File

@ -19,6 +19,7 @@ import Data.Foldable (find)
import Data.Hashable (Hashable) import Data.Hashable (Hashable)
import Data.HashSet (HashSet) import Data.HashSet (HashSet)
import qualified Data.HashSet as HashSet import qualified Data.HashSet as HashSet
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import Data.Maybe (isJust, isNothing) import Data.Maybe (isJust, isNothing)
import Data.List (nub) 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 -- 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 -- put them in the right order in the gallery
sortEx :: !Text, sortEx :: !Text,
updates :: !(Map Day Text),
title :: !Text, title :: !Text,
artist :: !(Maybe Artist), -- nothing = me, obv artist :: !(Maybe Artist), -- nothing = me, obv
nsfwOnly :: !Bool, 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 "month" Info Int where getField = #second . #dmy
instance HasField "day" Info Int where getField = #third . #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 :: Bool -> Info -> Maybe Text
descFor nsfw (Info {desc, nsfwDesc}) = desc <> (guard nsfw *> nsfwDesc) 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 linksFor nsfw = if nsfw then #links else #sfwLinks
instance Ord Info where 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 newtype NoThumb = NoThumb FilePath
@ -150,7 +157,8 @@ addSuffix suf path =
instance FromYAML Info where instance FromYAML Info where
parseYAML = YAML.withMap "info" \m -> parseYAML = YAML.withMap "info" \m ->
Info <$> m .: "date" Info <$> m .: "date"
<*> m .:? "sort" .!= "" <*> m .:? "sort" .!= ""
<*> m .:? "updates" .!= []
<*> m .: "title" <*> m .: "title"
<*> m .:? "artist" <*> m .:? "artist"
<*> m .:? "nsfw-only" .!= False <*> m .:? "nsfw-only" .!= False

View File

@ -5,10 +5,11 @@ import BuilderQQ
import Records () import Records ()
import Control.Exception import Control.Exception
import qualified Data.Map.Strict as Map
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
import qualified Data.Text as Strict import qualified Data.Text as Strict
import qualified Data.Text.Lazy as Lazy 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 System.FilePath (joinPath, splitPath, (</>))
import qualified System.Process as Proc import qualified System.Process as Proc
import Text.Read (readMaybe) import Text.Read (readMaybe)
@ -34,7 +35,8 @@ make root prefix nsfw dataDir dir info =
toLazyText <$> 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' :: 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 images <- withSizes (dataDir </> dir) $ imagesFor nsfw info
let undir = joinPath (replicate (length (splitPath dir)) "..") 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 descSection = makeDesc $ descFor nsfw info
let tagsList = makeTags undir $ tagsFor nsfw info let tagsList = makeTags undir $ tagsFor nsfw info
let linksList = extLinks $ linksFor 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 makePrefetch (Image {path}) = [b|<link rel=prefetch href=$path>|]
let prefetches = map (makePrefetch . #first) $ tail images 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" Nothing -> "by niss"
let thumb = getThumb "" info let thumb = getThumb "" info
let updateDate = ifJust (Map.lookupMax updates) \(formatDate -> u, _) ->
[b|<br> <span class=updated>updated $u</span>|]
pure [b|@0 pure [b|@0
<!DOCTYPE html> <!DOCTYPE html>
<html lang=en> <html lang=en>
@ -103,7 +109,9 @@ make' root prefix nsfw dataDir dir info@(Info {date, title, artist, bg}) = do
<header> <header>
<h1>$title</h1> <h1>$title</h1>
$artistTag $artistTag
<h2 id=date class="right corner">$formattedDate</h2> <h2 id=date class="right corner">
$formattedDate $updateDate
</h2>
</header> </header>
$buttonBar $buttonBar
@ -122,6 +130,8 @@ make' root prefix nsfw dataDir dir info@(Info {date, title, artist, bg}) = do
$tagsList $tagsList
$linksList $linksList
$updatesList
</div> </div>
</main> </main>
@ -217,6 +227,25 @@ extLink (Link {title, url}) = [b|@8
</a> </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 :: Day -> Builder
formatDate date = [b|$week $day $month $year|] where formatDate date = [b|$week $day $month $year|] where
(year, month', day') = Time.toGregorian date (year, month', day') = Time.toGregorian date

1
style/cake.svg Normal file
View 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

View File

@ -116,17 +116,12 @@ body {
box-shadow: var(--focus-box); box-shadow: var(--focus-box);
} }
.item[data-date]::before {
content: attr(data-date);
}
figure { figure {
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
figcaption, .item::before { figcaption .date, figcaption .title {
position: absolute; position: absolute;
width: 100%; width: 100%;
border: 1px solid var(--text-col); border: 1px solid var(--text-col);
@ -134,10 +129,11 @@ figcaption, .item::before {
text-align: center; text-align: center;
background: hsl(0, 0%, 0%, 75%); background: hsl(0, 0%, 0%, 75%);
font-size: 80%; font-size: 80%;
text-shadow: none;
} }
figcaption { bottom: -1px; left: -1px; } figcaption .date { top: -1px; left: -1px; }
.item::before { top: -1px; left: -1px; } figcaption .title { bottom: -1px; left: -1px; }
.year-marker { .year-marker {
grid-area: auto / 1; grid-area: auto / 1;
@ -164,19 +160,31 @@ figcaption { bottom: -1px; left: -1px; }
transform: scaleX(110%); transform: scaleX(110%);
} }
.item.nsfw::after { .item.nsfw::before, .item[data-updated="true"]::after {
--size: calc(1/4 * var(--image-size));
content: url(../18_plus_white.svg);
height: var(--size); height: var(--size);
width: var(--size); width: var(--size);
display: inline-block; display: inline-block;
position: absolute; 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); top: calc(1em + 3px);
right: 3px; right: 3px;
transform: rotate(var(--nsfw-sticker-rotate));
mix-blend-mode: multiply; 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 { footer {
@ -187,30 +195,33 @@ footer {
@media (hover) { @media (hover) {
.item:hover figcaption, .item:hover::before { .item:hover .date, .item:hover .title,
.item:hover::before, .item:hover::after {
filter: opacity(20%); filter: opacity(20%);
} }
@media (prefers-reduced-motion) {
.item:hover figcaption {
transform: translateY(80%);
}
}
@media (prefers-reduced-motion: no-preference) { @media (prefers-reduced-motion: no-preference) {
figcaption, .item::before { figcaption .date, figcaption .title, .item::before, .item::after {
transition-property: filter, transform; transition-property: filter, transform;
transition-duration: 0.25s; transition-duration: 0.15s;
transition-timing-function: ease-in-out; transition-timing-function: ease-in-out;
} }
.item:hover figcaption { .item:hover .title {
transform: translate(-20%, 80%) rotateZ(7deg); transform: translate(-20%, 80%) rotateZ(7deg);
} }
.item:hover::before { .item:hover .date {
transform: translate(20%, -80%) rotateZ(7deg); 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; height: min-content;
} }
figcaption { figcaption .date, figcaption .title {
position: initial; position: initial;
} }
figcaption .date::after {
content: ':';
}
.item a { .item a {
display: block; display: block;
height: var(--image-size); height: var(--image-size);

View File

@ -132,6 +132,28 @@ body {
margin: 0.35em; 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 { footer {
text-align: center; text-align: center;
margin-top: 1em; margin-top: 1em;

1
style/sparkles.svg Normal file
View 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