feat: massive refactor

This commit is contained in:
Cory Dransfeldt 2024-10-09 18:10:28 -07:00
parent d424082c95
commit 1880790c05
No known key found for this signature in database
38 changed files with 245 additions and 761 deletions

View file

@ -1,40 +1,40 @@
#tracks-recent,
#tracks-window,
#tracks-chart,
#tracks-recent ~ .tracks-recent,
#tracks-window ~ .tracks-window {
#tracks-chart ~ .tracks-chart {
display: none;
}
#tracks-recent:checked ~ .tracks-recent,
#tracks-window:checked ~ .tracks-window {
#tracks-chart:checked ~ .tracks-chart {
display: block;
}
input[id="tracks-recent"] ~ .tracks-recent,
input[id="tracks-window"] ~ .tracks-window {
input[id="tracks-chart"] ~ .tracks-chart {
margin-top: var(--spacing-base);
}
input[id="tracks-recent"] ~ [for="tracks-recent"]:has(+ [for="tracks-window"]) {
input[id="tracks-recent"] ~ [for="tracks-recent"]:has(+ [for="tracks-chart"]) {
margin-right: var(--spacing-xs);
}
#tracks-recent:checked ~ [for="tracks-recent"],
#tracks-window:checked ~ [for="tracks-window"] {
#tracks-chart:checked ~ [for="tracks-chart"] {
cursor: not-allowed;
border-color: var(--accent-color);
background-color: var(--accent-color);
}
#tracks-recent:not(:checked) ~ [for="tracks-recent"],
#tracks-window:not(:checked) ~ [for="tracks-window"] {
#tracks-chart:not(:checked) ~ [for="tracks-chart"] {
color: var(--accent-color);
background: transparent;
}
#tracks-recent:not(:checked) ~ [for="tracks-recent"]:hover,
#tracks-recent:not(:checked) ~ [for="tracks-recent"]:active,
#tracks-window:not(:checked) ~ [for="tracks-window"]:hover,
#tracks-window:not(:checked) ~ [for="tracks-window"]:active {
#tracks-chart:not(:checked) ~ [for="tracks-chart"]:hover,
#tracks-chart:not(:checked) ~ [for="tracks-chart"]:active {
color: var(--accent-color-hover);
}

View file

@ -6,21 +6,11 @@ const SUPABASE_KEY = process.env.SUPABASE_KEY
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
const fetchAlbumReleases = async () => {
const today = DateTime.utc().startOf('day')
const today = DateTime.utc().startOf('day').toSeconds()
const { data, error } = await supabase
.from('optimized_album_releases')
.select(`
name,
release_date,
release_link,
total_plays,
art,
artist_name,
artist_description,
artist_total_plays,
artist_country,
artist_favorite
`)
.select('*')
if (error) {
console.error('Error fetching data:', error)
@ -28,31 +18,18 @@ const fetchAlbumReleases = async () => {
}
const all = data.map(album => {
const releaseDate = DateTime.fromISO(album['release_date']).toUTC().startOf('day')
const releaseDate = DateTime.fromSeconds(album['release_timestamp']).toUTC().startOf('day')
return {
artist: {
name: album['artist_name'],
description: album['artist_description'],
total_plays: album['artist_total_plays'],
country: album['artist_country'],
favorite: album['artist_favorite'],
url: album['artist_url'],
},
title: album['name'],
...album,
description: album['artist']['description'],
date: releaseDate.toLocaleString(DateTime.DATE_FULL),
description: album['artist_description'],
url: album['release_link'],
image: album['art'] ? `/${album['art']}` : '',
total_plays: album['total_plays'],
release_date: releaseDate,
type: 'album-release',
timestamp: releaseDate.toSeconds(),
timestamp: releaseDate.toSeconds()
}
}).sort((a, b) => a['timestamp'] - b['timestamp'])
const upcoming = all.filter(album => (!album['total_plays'] || album['total_plays'] <= 0) && album['release_date'] > today)
const current = all.filter(album => album['release_date'] <= today)
const upcoming = all.filter(album => album['release_timestamp'] > today)
const current = all.filter(album => album['release_timestamp'] <= today)
return { all, upcoming, current }
}

View file

@ -13,27 +13,7 @@ const fetchAllArtists = async () => {
while (true) {
const { data, error } = await supabase
.from('optimized_artists')
.select(`
id,
name_string,
url,
tentative,
total_plays,
country,
description,
favorite,
genre,
emoji,
tattoo,
art,
albums,
concerts,
books,
movies,
posts,
related_artists,
shows
`)
.select('*')
.range(rangeStart, rangeStart + PAGE_SIZE - 1)
if (error) {
@ -51,49 +31,8 @@ const fetchAllArtists = async () => {
const processArtists = (artists) => {
return artists.map(artist => ({
name: artist['name_string'],
tentative: artist['tentative'],
totalPlays: artist['total_plays'],
...artist,
country: parseCountryField(artist['country']),
description: artist['description'],
favorite: artist['favorite'],
genre: {
name: artist['genre']['name'],
url: artist['genre']['url'],
},
emoji: artist['emoji'],
tattoo: artist['tattoo'],
image: artist['art'] ? `/${artist['art']}` : '',
url: artist['url'],
albums: (artist['albums'] || []).map(album => ({
name: album['name'],
releaseYear: album['release_year'],
totalPlays: album['total_plays'],
art: album.art ? `/${album['art']}` : ''
})).sort((a, b) => a['release_year'] - b['release_year']),
concerts: artist['concerts'] ? artist['concerts'].sort((a, b) => new Date(b['date']) - new Date(a['date'])) : null,
books: artist['books'] ? artist['books'].map(book => ({
title: book['title'],
author: book['author'],
description: book['description'],
url: `/books/${book['isbn']}`,
})).sort((a, b) => a['title'].localeCompare(b['title'])) : null,
movies: artist['movies'] ? artist['movies'].map(movie => ({
title: movie['title'],
year: movie['year'],
url: `/watching/movies/${movie['tmdb_id']}`,
})).sort((a, b) => b['year'] - a['year']) : null,
shows: artist['shows'] ? artist['shows'].map(show => ({
title: show['title'],
year: show['year'],
url: `/watching/shows/${show['tmdb_id']}`,
})).sort((a, b) => b['year'] - a['year']) : null,
posts: artist['posts'] ? artist['posts'].map(post => ({
title: post['title'],
date: post['date'],
url: post['url'],
})).sort((a, b) => new Date(b['date']) - new Date(a['date'])) : null,
relatedArtists: artist['related_artists'] ? artist['related_artists'].sort((a, b) => a['name'].localeCompare(b['name'])) : null,
}))
}

View file

@ -12,33 +12,12 @@ const fetchAllBooks = async () => {
while (true) {
const { data, error } = await supabase
.from('optimized_books')
.select(`
id,
isbn,
date_finished,
author,
description,
title,
progress,
read_status,
star_rating,
review,
art,
favorite,
tattoo,
tags,
artists,
genres,
movies,
posts,
shows,
related_books
`)
.select('*')
.order('date_finished', { ascending: false })
.range(rangeStart, rangeStart + PAGE_SIZE - 1)
if (error) {
console.error('Error fetching data from Supabase:', error)
console.error('Error fetching books:', error)
break
}
@ -52,45 +31,11 @@ const fetchAllBooks = async () => {
const processBooks = (books) => {
return books.map(book => {
const dateFinished = new Date(book['date_finished'])
const year = dateFinished.getUTCFullYear()
const dateFinished = book['date_finished'] ? new Date(book['date_finished']) : null
const year = dateFinished && !isNaN(dateFinished.getTime()) ? dateFinished.getUTCFullYear() : null
return {
title: book['title'],
author: book['author'] || '',
review: book['review'],
rating: book['star_rating'] !== 'unrated' ? book['star_rating'] : '',
favorite: book['favorite'],
tattoo: book['tattoo'],
description: book['description'],
image: `/${book['art']}`,
url: `/books/${book['isbn']}`,
date: book['date_finished'],
status: book['read_status'],
progress: book['progress'],
tags: Array.isArray(book['tags']) ? book['tags'] : book['tags']?.split(',') || [],
type: 'book',
artists: book['artists'] ? book['artists'].sort((a, b) => a['name'].localeCompare(b['name'])) : null,
movies: book['movies'] ? book['movies'].map(movie => {
movie['url'] = `/watching/movies/${movie['tmdb_id']}`
return movie
}).sort((a, b) => b['year'] - a['year']) : null,
genres: book['genres'] ? book['genres'].sort((a, b) => a['name'].localeCompare(b['name'])) : null,
shows: book['shows'] ? book['shows'].map(show => {
show['url'] = `/watching/shows/${show['tmdb_id']}`
return show
}).sort((a, b) => b['year'] - a['year']) : null,
posts: book['posts'] ? book['posts'].map(post => ({
title: post['title'],
date: post['date'],
url: post['url'],
})).sort((a, b) => new Date(b['date']) - new Date(a['date'])) : null,
relatedBooks: book['related_books'] ? book['related_books'].map(relatedBook => ({
title: relatedBook['title'],
author: relatedBook['author'],
description: relatedBook['description'],
url: `/books/${relatedBook['isbn']}`,
})).sort((a, b) => a['title'].localeCompare(b['title'])) : null, // Add related books processing
...book,
year,
}
})
@ -112,5 +57,6 @@ const sortBooksByYear = (books) => {
export default async function () {
const books = await fetchAllBooks()
const processedBooks = processBooks(books)
return { all: processedBooks, years: sortBooksByYear(processedBooks) }
}

View file

@ -12,13 +12,7 @@ const fetchAllConcerts = async () => {
while (true) {
const { data, error } = await supabase
.from('optimized_concerts')
.select(`
id,
date,
artist,
venue,
concert_notes
`)
.select('*')
.range(rangeStart, rangeStart + PAGE_SIZE - 1)
if (error) {
@ -36,24 +30,9 @@ const fetchAllConcerts = async () => {
const processConcerts = (concerts) => {
return concerts.map(concert => ({
id: concert['id'],
type: 'concert',
date: concert['date'],
artist: concert['artist'] && typeof concert['artist'] === 'object' ? {
name: concert['artist'].name,
url: concert['artist'].url
} : { name: concert['artist'], url: null },
venue: concert['venue'] && typeof concert['venue'] === 'object' ? {
name: concert['venue'].name,
latitude: concert['venue'].latitude,
longitude: concert['venue'].longitude,
notes: concert['venue'].notes
} : null,
description: 'I went to (yet another) concert!',
notes: concert['concert_notes'],
url: `/music/concerts?id=${concert['id']}`,
artistUrl: concert['artist'] && typeof concert['artist'] === 'object' ? concert['artist'].url : null
})).sort((a, b) => new Date(b['date']) - new Date(a['date']))
...concert,
artist: concert.artist || { name: concert.artist_name_string, url: null },
}))
}
export default async function () {

View file

@ -4,53 +4,22 @@ const SUPABASE_URL = process.env.SUPABASE_URL
const SUPABASE_KEY = process.env.SUPABASE_KEY
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
const fetchGenresWithArtists = async () => {
const fetchGenres = async () => {
const { data, error } = await supabase
.from('optimized_genres')
.select(`
name,
description,
total_plays,
wiki_link,
url,
artists,
books,
movies,
posts
`)
.order('id', { ascending: true })
.select('*')
if (error) {
console.error('Error fetching genres with artists:', error)
return []
}
return data.map(genre => ({
...genre,
artists: genre['artists'],
url: genre['url'],
books: genre['books'] ? genre['books'].map(book => ({
title: book['title'],
author: book['author'],
description: book['description'],
url: `/books/${book['isbn']}`,
})).sort((a, b) => a['title'].localeCompare(b['title'])) : null,
movies: genre['movies'] ? genre['movies'].map(movie => ({
title: movie['title'],
year: movie['year'],
url: `/watching/movies/${movie['tmdb_id']}`,
})).sort((a, b) => b['year'] - a['year']) : null,
posts: genre['posts'] ? genre['posts'].map(post => ({
title: post['title'],
date: post['date'],
url: post['url'],
})).sort((a, b) => new Date(b['date']) - new Date(a['date'])) : null,
}))
return data
}
export default async function () {
try {
return await fetchGenresWithArtists()
return await fetchGenres()
} catch (error) {
console.error('Error fetching and processing genres:', error)
return []

View file

@ -5,24 +5,6 @@ const SUPABASE_KEY = process.env.SUPABASE_KEY
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
const PAGE_SIZE = 1000
const fetchAllTags = async () => {
const { data, error } = await supabase
.from('links_tags')
.select('links_id, tags(name)')
if (error) {
console.error('Error fetching all tags from Supabase:', error)
return {}
}
return data.reduce((acc, { links_id, tags }) => {
if (!tags || !tags.name) return acc
if (!acc[links_id]) acc[links_id] = []
acc[links_id].push(tags['name'])
return acc
}, {})
}
const fetchAllLinks = async () => {
let links = []
let page = 0
@ -30,9 +12,8 @@ const fetchAllLinks = async () => {
while (fetchMore) {
const { data, error } = await supabase
.from('links')
.select('*, authors (name, url, mastodon)')
.order('date', { ascending: false })
.from('optimized_links')
.select('*')
.range(page * PAGE_SIZE, (page + 1) * PAGE_SIZE - 1)
if (error) {
@ -49,15 +30,11 @@ const fetchAllLinks = async () => {
return links
}
const processLinks = (links, tagsByLinkId) => {
return links.map(link => {
link['tags'] = tagsByLinkId[link['id']] || []
link['type'] = 'link'
return link
})
}
export default async function () {
const [links, tagsByLinkId] = await Promise.all([fetchAllLinks(), fetchAllTags()])
return processLinks(links, tagsByLinkId)
try {
return await fetchAllLinks()
} catch (error) {
console.error('Error fetching and processing links:', error)
return []
}
}

View file

@ -13,34 +13,11 @@ const fetchAllMovies = async () => {
while (true) {
const { data, error } = await supabase
.from('optimized_movies')
.select(`
id,
tmdb_id,
last_watched,
title,
year,
collected,
plays,
favorite,
tattoo,
star_rating,
description,
review,
art,
backdrop,
tags,
artists,
books,
genres,
shows,
posts,
related_movies
`)
.order('last_watched', { ascending: false })
.select('*')
.range(rangeStart, rangeStart + PAGE_SIZE - 1)
if (error) {
console.error(error)
console.error('Error fetching movies:', error)
break
}
@ -53,62 +30,20 @@ const fetchAllMovies = async () => {
return movies
}
const processMovies = (movies) => {
return movies.map(item => ({
title: item['title'],
lastWatched: item['last_watched'],
dateAdded: item['last_watched'],
year: item['year'],
url: `/watching/movies/${item['tmdb_id']}`,
description: item['description'],
image: item['art'] ? `/${item['art']}` : '',
backdrop: item['backdrop'] ? `/${item['backdrop']}` : '',
plays: item['plays'],
collected: item['collected'],
favorite: item['favorite'],
tattoo: item['tattoo'],
rating: item['star_rating'],
review: item['review'],
type: 'movie',
tags: item['tags'] ? item['tags'].split(',') : [],
artists: item['artists'] ? item['artists'].sort((a, b) => a['name'].localeCompare(b['name'])) : null,
books: item['books'] ? item['books'].map(book => {
book['url'] = `/books/${book['isbn']}`
return book
}).sort((a, b) => a['title'].localeCompare(b['title'])) : null,
genres: item['genres'] ? item['genres'].sort((a, b) => a['title'].localeCompare(b['title'])) : null,
shows: item['shows'] ? item['shows'].map(show => {
show['url'] = `/watching/shows/${show['tmdb_id']}`
return show
}).sort((a, b) => b['year'] - a['year']) : null,
posts: item['posts'] ? item['posts'].map(post => ({
title: post['title'],
date: post['date'],
url: post['url'],
})).sort((a, b) => new Date(b['date']) - new Date(a['date'])) : null,
relatedMovies: item['related_movies'] ? item['related_movies'].map(movie => {
movie['url'] = `/watching/movies/${movie['tmdb_id']}`
return movie
}).sort((a, b) => b['year'] - a['year']) : null,
}))
}
export default async function () {
const year = DateTime.now().year
try {
const movies = await fetchAllMovies()
const processedMovies = processMovies(movies)
const filterMovies = (condition) => processedMovies.filter(condition)
const formatMovieData = (movies) => movies.map(movie => movie)
const favoriteMovies = filterMovies(movie => movie['favorite'])
const recentlyWatchedMovies = filterMovies(movie => movie['lastWatched'] && year - DateTime.fromISO(movie['lastWatched']).year <= 3).sort((a, b) => new Date(b['lastWatched']) - new Date(a['lastWatched']))
const filterMovies = (condition) => movies.filter(condition)
const favoriteMovies = filterMovies(movie => movie.favorite)
const recentlyWatchedMovies = filterMovies(movie => movie.last_watched && year - DateTime.fromISO(movie.last_watched).year <= 3)
return {
movies: formatMovieData(processedMovies),
watchHistory: formatMovieData(filterMovies(movie => movie['lastWatched'])),
recentlyWatched: formatMovieData(recentlyWatchedMovies),
favorites: formatMovieData(favoriteMovies).sort((a, b) => a['title'].localeCompare(b['title'])),
movies,
watchHistory: filterMovies(movie => movie.last_watched),
recentlyWatched: recentlyWatchedMovies,
favorites: favoriteMovies.sort((a, b) => a.title.localeCompare(b.title)),
}
} catch (error) {
console.error('Error fetching and processing movies data:', error)
@ -116,7 +51,7 @@ export default async function () {
movies: [],
watchHistory: [],
recentlyWatched: [],
favorites: [],
favorites: []
}
}
}

View file

@ -5,14 +5,14 @@ const SUPABASE_KEY = process.env.SUPABASE_KEY
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
const PAGE_SIZE = 1000
const fetchDataFromView = async (viewName, fields) => {
const fetchDataFromView = async (viewName) => {
let rows = []
let rangeStart = 0
while (true) {
const { data, error } = await supabase
.from(viewName)
.select(fields)
.select('*')
.order('listened_at', { ascending: false })
.range(rangeStart, rangeStart + PAGE_SIZE - 1)
@ -32,36 +32,40 @@ const fetchDataFromView = async (viewName, fields) => {
return rows
}
const fetchGenreMapping = async () => {
const { data, error } = await supabase
.from('genres')
.select('id, name')
if (error) {
console.error('Error fetching genres:', error)
return {}
}
return data.reduce((acc, genre) => {
acc[genre['id']] = genre['name']
return acc
}, {})
}
const aggregateData = (data, groupByField, groupByType, genreMapping) => {
const aggregateData = (data, groupByField, groupByType) => {
const aggregation = {}
data.forEach(item => {
const key = item[groupByField]
if (!aggregation[key]) {
let imageField = ''
switch (groupByType) {
case 'artist':
imageField = item['artist_art']
break
case 'album':
imageField = item['album_art']
break
case 'track':
imageField = item['album_art']
break
default:
imageField = ''
}
aggregation[key] = {
title: item[groupByField],
plays: 0,
url: item['artist_url'],
image: `/${item[groupByType]}`,
type: groupByType === 'artist_art' ? 'artist' : groupByType === 'album_art' ? 'album' : groupByType,
genre: genreMapping[item['artist_genres']] || ''
image: imageField,
genre: item['artist_genres'],
type: groupByType
}
if (groupByType === 'track' || groupByType === 'album_art') aggregation[key]['artist'] = item['artist_name']
if (groupByType === 'track' || groupByType === 'album') aggregation[key]['artist'] = item['artist_name']
}
aggregation[key].plays++
})
@ -74,66 +78,62 @@ const buildRecents = (data) => {
artist: listen['artist_name'],
url: listen['artist_url'],
timestamp: listen['listened_at'],
image: `/${listen['album_art']}`
})).sort((a, b) => b.timestamp - a.timestamp)
image: listen['album_art'],
type: 'track'
})).sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp))
}
const aggregateGenres = (data, genreMapping) => {
const aggregateGenres = (data) => {
const genreAggregation = {}
data.forEach(item => {
const genre = genreMapping[item['artist_genres']] || ''
if (!genreAggregation[genre]) genreAggregation[genre] = { name: genre, url: item['genre_url'], plays: 0 }
const genre = item['genre_name'] || ''
const genreUrl = item['genre_url'] || ''
if (!genreAggregation[genre]) {
genreAggregation[genre] = {
name: genre,
url: genreUrl,
plays: 0,
type: 'genre'
}
}
genreAggregation[genre]['plays']++
})
return Object.values(genreAggregation).sort((a, b) => b['plays'] - a['plays'])
}
export default async function () {
const selectFields = `
listened_at,
track_name,
artist_name,
album_name,
album_key,
artist_art,
artist_genres,
artist_country,
album_art,
artist_url,
genre_url
`
try {
const genreMapping = await fetchGenreMapping()
const [recentTracks, monthTracks, threeMonthTracks] = await Promise.all([
fetchDataFromView('recent_tracks', selectFields),
fetchDataFromView('month_tracks', selectFields),
fetchDataFromView('three_month_tracks', selectFields)
fetchDataFromView('recent_tracks'),
fetchDataFromView('month_tracks'),
fetchDataFromView('three_month_tracks')
])
return {
recent: buildRecents(recentTracks),
week: {
artists: aggregateData(recentTracks, 'artist_name', 'artist_art', genreMapping),
albums: aggregateData(recentTracks, 'album_name', 'album_art', genreMapping),
tracks: aggregateData(recentTracks, 'track_name', 'track', genreMapping),
genres: aggregateGenres(recentTracks, genreMapping),
artists: aggregateData(recentTracks, 'artist_name', 'artist'),
albums: aggregateData(recentTracks, 'album_name', 'album'),
tracks: aggregateData(recentTracks, 'track_name', 'track'),
genres: aggregateGenres(recentTracks),
totalTracks: recentTracks.length.toLocaleString('en-US')
},
month: {
artists: aggregateData(monthTracks, 'artist_name', 'artist_art', genreMapping),
albums: aggregateData(monthTracks, 'album_name', 'album_art', genreMapping),
tracks: aggregateData(monthTracks, 'track_name', 'track', genreMapping),
genres: aggregateGenres(monthTracks, genreMapping),
artists: aggregateData(monthTracks, 'artist_name', 'artist'),
albums: aggregateData(monthTracks, 'album_name', 'album'),
tracks: aggregateData(monthTracks, 'track_name', 'track'),
genres: aggregateGenres(monthTracks),
totalTracks: monthTracks.length.toLocaleString('en-US')
},
threeMonth: {
artists: aggregateData(threeMonthTracks, 'artist_name', 'artist_art', genreMapping),
albums: aggregateData(threeMonthTracks, 'album_name', 'album_art', genreMapping),
tracks: aggregateData(threeMonthTracks, 'track_name', 'track', genreMapping),
genres: aggregateGenres(threeMonthTracks, genreMapping),
artists: aggregateData(threeMonthTracks, 'artist_name', 'artist'),
albums: aggregateData(threeMonthTracks, 'album_name', 'album'),
tracks: aggregateData(threeMonthTracks, 'track_name', 'track'),
genres: aggregateGenres(threeMonthTracks),
totalTracks: threeMonthTracks.length.toLocaleString('en-US')
}
}

View file

@ -3,43 +3,8 @@ import { createClient } from '@supabase/supabase-js'
const SUPABASE_URL = process.env['SUPABASE_URL']
const SUPABASE_KEY = process.env['SUPABASE_KEY']
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
const PAGE_SIZE = 250
const fetchBlockData = async (collection, itemId) => {
const { data, error } = await supabase
.from(collection)
.select(collection === 'hero' ? '*, image(filename_disk)' : '*')
.eq('id', itemId)
.single()
if (error) {
console.error(`Error fetching data from ${collection} for item ${itemId}:`, error)
return null
}
return data
}
const fetchAllBlocks = async () => {
const { data, error } = await supabase
.from('pages_blocks')
.select('pages_id, collection, item, sort')
if (error) {
console.error('Error fetching all blocks from Supabase:', error)
return {}
}
return data.reduce((acc, block) => {
if (!acc[block['pages_id']]) {
acc[block['pages_id']] = []
}
acc[block['pages_id']].push(block)
return acc
}, {})
}
const fetchAllPages = async () => {
let pages = []
let page = 0
@ -65,40 +30,9 @@ const fetchAllPages = async () => {
return pages
}
const processPages = async (pages, blocksByPageId) => {
return Promise.all(pages.map(async page => {
const blocks = blocksByPageId[page['id']] || []
page['blocks'] = await Promise.all(blocks.map(async block => {
const blockData = await fetchBlockData(block['collection'], block['item'])
if (!blockData) return {
'type': block['collection'],
'sort': block['sort']
}
return {
'type': block['collection'],
'sort': block['sort'],
...blockData
}
})).then(blocks => blocks.filter(block => block !== null))
page['blocks'].sort((a, b) => a['sort'] - b['sort'])
if (page['open_graph_image']) page['open_graph_image'] = page['open_graph_image']['filename_disk']
return page
}))
}
export default async function () {
try {
const [pages, blocksByPageId] = await Promise.all([
fetchAllPages(),
fetchAllBlocks()
])
return await processPages(pages, blocksByPageId)
return await fetchAllPages()
} catch (error) {
console.error('Error fetching and processing pages:', error)
return []

View file

@ -9,7 +9,6 @@ const fetchAllPosts = async () => {
let posts = []
let page = 0
let fetchMore = true
const uniquePosts = new Set()
while (fetchMore) {
const { data, error } = await supabase
@ -25,44 +24,18 @@ const fetchAllPosts = async () => {
if (data.length < PAGE_SIZE) fetchMore = false
for (const post of data) {
if (uniquePosts.has(post['url'])) continue
uniquePosts.add(post['url'])
posts.push(post)
}
posts = posts.concat(data)
page++
}
return posts
}
const processPosts = async (posts) => {
return Promise.all(posts.map(async post => {
post['artists'] = post['artists'] ? post['artists'].sort((a, b) => a['name'].localeCompare(b['name'])) : null
post['books'] = post['books'] ? post['books'].map(book => ({
title: book['title'],
author: book['author'],
description: book['description'],
url: `/books/${book['isbn']}`,
})).sort((a, b) => a['title'].localeCompare(b['title'])) : null
post['movies'] = post['movies'] ? post['movies'].map(movie => {
movie['url'] = `/watching/movies/${movie['tmdb_id']}`
return movie
}).sort((a, b) => b['year'] - a['year']) : null
post['genres'] = post['genres'] ? post['genres'].sort((a, b) => a['name'].localeCompare(b['name'])) : null
post['shows'] = post['shows'] ? post['shows'].map(show => {
show['url'] = `/watching/shows/${show['tmdb_id']}`
return show
}).sort((a, b) => b['year'] - a['year']) : null
if (post['image']) post['image'] = post['image']['filename_disk']
return post
}))
}
export default async function () {
const posts = await fetchAllPosts()
return await processPosts(posts)
try {
return await fetchAllPosts()
} catch (error) {
console.error('Error fetching and processing posts:', error)
return []
}
}

View file

@ -12,26 +12,7 @@ const fetchAllShows = async () => {
while (true) {
const { data, error } = await supabase
.from('optimized_shows')
.select(`
id,
tmdb_id,
title,
year,
collected,
favorite,
tattoo,
description,
review,
art,
backdrop,
tags,
episodes,
artists,
books,
movies,
posts,
related_shows
`)
.select('*')
.range(rangeStart, rangeStart + PAGE_SIZE - 1)
if (error) {
@ -47,136 +28,31 @@ const fetchAllShows = async () => {
return shows
}
const prepareShowData = (show) => ({
...show,
image: show['art'] ? `/${show['art']}` : '',
backdrop: show['backdrop'] ? `/${show['backdrop']}` : '',
url: `/watching/shows/${show['tmdb_id']}`,
episodes: show['episodes'] || [],
tattoo: show['tattoo'],
tags: Array.isArray(show['tags']) ? show['tags'] : show['tags']?.split(',') || [],
movies: show['movies'] ? show['movies'].map(movie => {
movie['url'] = `/watching/movies/${movie['tmdb_id']}`
return movie
}).sort((a, b) => b['year'] - a['year']) : null,
books: show['books'] ? show['books'].map(book => ({
title: book['title'],
author: book['author'],
description: book['description'],
url: `/books/${book['isbn']}`,
})).sort((a, b) => a['title'].localeCompare(b['title'])) : null,
posts: show['posts'] ? show['posts'].map(post => ({
title: post['title'],
date: post['date'],
url: post['url'],
})).sort((a, b) => new Date(b['date']) - new Date(a['date'])) : null,
relatedShows: show['related_shows'] ? show['related_shows'].map(relatedShow => ({
title: relatedShow['title'],
year: relatedShow['year'],
url: `/watching/shows/${relatedShow['tmdb_id']}`,
})).sort((a, b) => b['year'] - a['year']) : null,
artists: show['artists'] ? show['artists'].sort((a, b) => a['name'].localeCompare(b['name'])) : null
})
const prepareEpisodeData = (show) => show['episodes'].map(episode => ({
...episode,
show_title: show['title'],
show_tmdb_id: show['tmdb_id'],
show_year: show['year'],
collected: show['collected'],
favorite: show['favorite'],
image: show['image'],
backdrop: show['backdrop'],
episode_number: episode['episode_number'],
season_number: episode['season_number'],
last_watched_at: episode['last_watched_at']
}))
const formatEpisodeData = (episodes) => {
const showEpisodesMap = {}
episodes.forEach(episode => {
const showTmdbId = episode['show_tmdb_id']
const showYear = episode['show_year']
if (!showEpisodesMap[showTmdbId]) {
showEpisodesMap[showTmdbId] = {
title: episode['show_title'],
tmdbId: showTmdbId,
year: showYear,
collected: episode['collected'],
favorite: episode['favorite'],
dateAdded: episode['last_watched_at'],
lastWatchedAt: episode['last_watched_at'],
episodes: [],
image: episode['image'],
backdrop: episode['backdrop'],
}
}
showEpisodesMap[showTmdbId].episodes.push({
name: episode['show_title'],
url: `/watching/shows/${showTmdbId}`,
subtext: `S${episode['season_number']}E${episode['episode_number']}`,
episode: episode['episode_number'],
season: episode['season_number'],
tmdbId: showTmdbId,
year: showYear,
type: 'tv',
dateAdded: episode['last_watched_at'],
lastWatchedAt: episode['last_watched_at'],
image: episode['image'],
backdrop: episode['backdrop'],
})
})
return Object.values(showEpisodesMap).sort((a, b) => new Date(b['episodes'][0]['lastWatchedAt']) - new Date(a['episodes'][0]['lastWatchedAt'])).flatMap(show => {
const startingEpisode = show['episodes'][show['episodes'].length - 1]['episode']
const startingSeason = show['episodes'][show['episodes'].length - 1]['season']
const endingEpisode = show['episodes'][0]['episode']
const endingSeason = show['episodes'][0]['season']
if (show.episodes.length > 1) {
return {
name: show['title'],
url: `/watching/shows/${show['tmdbId']}`,
subtext: `S${startingSeason}E${startingEpisode} - S${endingSeason}E${endingEpisode}`,
startingEpisode,
startingSeason,
episode: endingEpisode,
season: endingSeason,
tmdbId: show['tmdbId'],
year: show['year'],
collected: show['collected'],
favorite: show['favorite'],
type: 'tv-range',
image: show['image'],
backdrop: show['backdrop'],
}
} else {
return show['episodes'][0]
}
})
}
export default async function () {
try {
const rawShows = await fetchAllShows()
const shows = rawShows.map(prepareShowData)
const episodes = shows.flatMap(prepareEpisodeData).sort((a, b) => new Date(b['last_watched_at']) - new Date(a['last_watched_at']))
const favoriteShows = shows.filter(show => show.favorite)
const shows = await fetchAllShows()
const watchedShows = shows.filter(show => show['last_watched_at'] !== null)
const episodes = watchedShows.map(show => ({
title: show['episode']['title'],
year: show['year'],
formatted_episode: show['episode']['formatted_episode'],
url: show['episode']['url'],
image: show['episode']['image'],
backdrop: show['episode']['backdrop'],
last_watched_at: show['episode']['last_watched_at'],
type: 'tv'
}))
return {
shows,
watchHistory: formatEpisodeData(episodes),
recentlyWatched: formatEpisodeData(episodes.slice(0, 225)),
favorites: formatEpisodeData(favoriteShows.flatMap(prepareEpisodeData)).sort((a, b) => a['name'].localeCompare(b['name'])),
recentlyWatched: episodes.slice(0, 225),
favorites: shows.filter(show => show.favorite).sort((a, b) => a.title.localeCompare(b.title)),
}
} catch (error) {
console.error('Error fetching and processing shows data:', error)
return {
shows: [],
watchHistory: [],
recentlyWatched: [],
favorites: [],
}

View file

@ -47,7 +47,7 @@
{%- assign pageDescription = description -%}
{%- endif -%}
{%- assign ogImage = 'https://cdn.coryd.dev/' | append: globals.opengraph_default -%}
{%- assign ogImage = 'https://cdn.coryd.dev/' | append: globals.avatar | append: "?class=w800" -%}
{%- case schema -%}
{%- when 'music' -%}
{%- assign ogImage = 'https://cdn.coryd.dev' | append: page.image -%}
@ -61,11 +61,20 @@
{%- when 'watching' -%}
{%- assign featuredMovie = movies.recentlyWatched | first -%}
{%- assign ogImage = 'https://cdn.coryd.dev' | append: featuredMovie.backdrop -%}
{%- when 'watching-shows' -%}
{%- assign featuredShow = tv.recentlyWatched | first -%}
{%- assign ogImage = 'https://cdn.coryd.dev' | append: featuredShow.backdrop -%}
{%- when 'favorite-movies' -%}
{%- assign featuredMovie = movies.favorites| shuffleArray | first -%}
{%- assign ogImage = 'https://cdn.coryd.dev' | append: featuredMovie.backdrop -%}
{%- when 'favorite-shows' -%}
{%- assign featuredShow = tv.favorites | shuffleArray | first -%}
{%- assign ogImage = 'https://cdn.coryd.dev' | append: featuredShow.backdrop -%}
{%- when 'books' -%}
{%- assign featuredBook = books.all | bookStatus: 'started' | reverse | first -%}
{%- assign ogImage = 'https://cdn.coryd.dev' | append: featuredBook.image -%}
{%- when 'books-year' -%}
{%- assign featuredBook = books.all | bookStatus: 'finished' | bookFinishedYear: year.value | bookSortDescending | first -%}
{%- assign featuredBook = books.all | bookStatus: 'finished' | bookFinishedYear: year.value | first -%}
{%- assign ogImage = 'https://cdn.coryd.dev' | append: featuredBook.image -%}
{%- when 'book' -%}
{%- assign ogImage = 'https://cdn.coryd.dev' | append: book.image -%}
@ -95,12 +104,12 @@
<meta property="og:url" content="{{ fullUrl }}" />
<meta property="og:image" content="{{ ogImage }}?class=w800" />
<meta name="theme-color" content="{{ globals.theme_color }}" />
<meta name="fediverse:creator" content="@cory@follow.coryd.dev" />
<meta name="fediverse:creator" content="{{ globals.mastodon }}" />
<meta name="generator" content="Eleventy">
<meta name="robots" content="noai, noimageai">
<link href="https://cdn.coryd.dev/{{ globals.favicon_ico }}?class=w50&v={% appVersion %}" rel="icon" sizes="any">
<link href="https://cdn.coryd.dev/{{ globals.favicon_svg }}?class=w50&v={% appVersion %}" rel="icon" type="image/svg+xml">
<link href="https://cdn.coryd.dev/{{ globals.apple_touch_icon }}?class=w200&v={% appVersion %}" rel="apple-touch-icon">
<link href="https://cdn.coryd.dev{{ globals.avatar_transparent }}?class=w50&v={% appVersion %}" rel="icon" sizes="any">
<link href="https://cdn.coryd.dev{{ globals.avatar_transparent }}?class=w50&v={% appVersion %}&type=svg" rel="icon" type="image/svg+xml">
<link href="https://cdn.coryd.dev{{ globals.avatar_transparent }}?class=w200&v={% appVersion %}" rel="apple-touch-icon">
<link type="application/atom+xml" rel="alternate" title="Posts / {{ globals.site_name }}" href="https://coryd.dev/feeds/posts">
<link rel="alternate" href="https://coryd.dev/feeds/links" title="Links / {{ globals.site_name }}" type="application/rss+xml">
<link rel="alternate" href="https://coryd.dev/feeds/movies" title="Movies / {{ globals.site_name }}'s movies feed" type="application/rss+xml">

View file

@ -1,13 +1,13 @@
<img
srcset="
https://cdn.coryd.dev/{{ image }}?class=bannersm&type=webp 256w,
https://cdn.coryd.dev/{{ image }}?class=bannermd&type=webp 512w,
https://cdn.coryd.dev/{{ image }}?class=bannerbase&type=webp 1024w
https://cdn.coryd.dev{{ image }}?class=bannersm&type=webp 256w,
https://cdn.coryd.dev{{ image }}?class=bannermd&type=webp 512w,
https://cdn.coryd.dev{{ image }}?class=bannerbase&type=webp 1024w
"
sizes="(max-width: 450px) 256px,
(max-width: 850px) 512px
1024px"
src="https://cdn.coryd.dev/{{ image }}?class=bannersm&type=webp"
src="https://cdn.coryd.dev{{ image }}?class=bannersm&type=webp"
alt="{{ alt }}"
class="image-banner"
loading="lazy"

View file

@ -8,7 +8,7 @@
{%- elsif block.type == 'rss_banner' -%}
{% render "partials/blocks/banners/rss.liquid", url:block.url, text:block.text %}
{%- elsif block.type == 'hero' -%}
{% render "partials/blocks/hero.liquid", image:block.image.filename_disk, alt:block.alt_text %}
{% render "partials/blocks/hero.liquid", image:block.image, alt:block.alt %}
{%- elsif block.type == 'markdown' -%}
{{ block.text | markdown }}
{%- elsif block.type == 'divider' -%}

View file

@ -4,12 +4,12 @@
"home_page_url": "{{ permalink | absoluteUrl | escape }}",
"feed_url": "{{ permalink | absoluteUrl | escape }}.json",
"description": "{{ globals.site_description | escape }}",
"icon": "https://cdn.coryd.dev/{{ globals.feed_image | escape }}?class=w200&v={% appVersion %}",
"favicon": "https://cdn.coryd.dev/{{ globals.favicon_ico | escape }}?class=w50&v={% appVersion %}",
"icon": "https://cdn.coryd.dev{{ globals.avatar | escape }}?class=w200&v={% appVersion %}",
"favicon": "https://cdn.coryd.dev{{ globals.avatar | escape }}?class=w50&v={% appVersion %}",
"authors": [{
"name": "{{ globals.site_name }}",
"url": "{{ globals.url | escape }}",
"avatar": "https://cdn.coryd.dev/{{ globals.avatar | escape }}?class=w200&v={% appVersion %}"
"avatar": "https://cdn.coryd.dev{{ globals.avatar | escape }}?class=w200&v={% appVersion %}"
}],
"items": [
{%- assign entries = data | normalizeEntries: 20 -%}

View file

@ -11,7 +11,7 @@
<image>
<title><![CDATA[{{ title }}]]></title>
<link>{{ permalink | absoluteUrl }}</link>
<url>{{ "https://cdn.coryd.dev/" | append: globals.feed_image | append: "?class=w200" }}</url>
<url>{{ "https://cdn.coryd.dev" | append: globals.avatar | append: "?class=w200" }}</url>
<width>144</width>
<height>144</height>
</image>

View file

@ -1,7 +1,8 @@
{%- assign currentYear = 'now' | date: "%Y" -%}
{%- assign track = music.week.tracks | first -%}
{%- assign show = tv.recentlyWatched | first -%}
{%- assign movie = movies.recentlyWatched | first -%}
{%- assign book = books | bookStatus: 'finished' | bookSortDescending | first -%}
{%- assign book = books | bookFinishedYear: currentYear | first -%}
{%- assign link = links | first -%}
<article>
<h2>
@ -10,10 +11,10 @@
</h2>
<ul>
<li><span class="music">Top track this week:</span> <a href="{{ track.url }}">{{ track.title }} by {{ track.artist }}</a></li>
<li><span class="tv">Last episode watched:</span> <strong class="highlight-text">S{{ show.season }}E{{ show.episode }}</strong> of <a href="{{ show.url }}">{{ show.name }}</a></li>
<li><span class="tv">Last episode watched:</span> <strong class="highlight-text">{{ show.formatted_episode }}</strong> of <a href="{{ show.url }}">{{ show.title }}</a></li>
<li><span class="movies">Last movie watched:</span> <a href="{{ movie.url }}">{{ movie.title }}</a>{%- if movie.rating %} ({{ movie.rating }}){%- endif -%}</li>
<li><span class="books">Last book finished:</span> <a href="{{ book.url }}">{{ book.title }}</a> by {{ book.author }}{%- if book.rating %} ({{ book.rating }}){%- endif -%}</li>
<li><span class="link">Last link shared:</span> <a href="{{ link.link }}">{{ link.title }}</a>{% if link.authors %} via <a href="{{ link.authors.url }}">{{ link.authors.name }}</a>{% endif %}</li>
<li><span class="link">Last link shared:</span> <a href="{{ link.link }}">{{ link.title }}</a>{% if link.author %} via <a href="{{ link.author.url }}">{{ link.author.name }}</a>{% endif %}</li>
</ul>
{% render "partials/blocks/banners/rss.liquid", url: "/feeds", text: "Subscribe to my movies, books, links or activity feed(s)" %}
</article>

View file

@ -15,7 +15,7 @@
({{ item.year }})
</div>
{%- else -%}
<div class="header">{{ item.name }}</div>
<div class="header">{{ item.title }}</div>
<div class="subheader">({{ item.year }})</div>
{%- endif -%}
</div>

View file

@ -6,8 +6,9 @@ permalink: "/books/index.html"
updated: "now"
schema: books
---
{%- assign currentYear = 'now' | date: "%Y" -%}
{%- assign bookData = books.all | bookStatus: 'started' | reverse -%}
{%- assign currentBookCount = books.all | currentBookCount -%}
{%- assign currentBookCount = books.all | bookFinishedYear: currentYear | size -%}
<h2>Currently reading</h2>
<p>Here's what I'm reading at the moment. I've finished <strong class="highlight-text">{{ currentBookCount }} books</strong> this year.</p>
<p>{{ books.years | bookYearLinks }}</p>

View file

@ -7,7 +7,7 @@ pagination:
permalink: "/books/years/{{ year.value }}.html"
schema: books-year
---
{%- assign bookData = year.data | bookStatus: 'finished' | bookSortDescending -%}
{%- assign bookData = year.data | bookStatus: 'finished' -%}
{%- assign bookDataFavorites = bookData | bookFavorites -%}
{%- capture favoriteBooks -%}{{ bookDataFavorites | shuffleArray | mediaLinks: "book", 5 }}{%- endcapture -%}
{%- capture currentYear -%}{% currentYear %}{%- endcapture -%}

View file

@ -19,7 +19,7 @@ permalink: "/links/{% if pagination.pageNumber > 0 %}{{ pagination.pageNumber }}
<a href="{{ link.link }}" title="{{ link.title | escape }}">
<strong>{{ link.title }}</strong>
</a>
{% if link.authors %} via <a href="{{ link.authors.url }}">{{ link.authors.name }}</a>{% endif %}
{% if link.author %} via <a href="{{ link.author.url }}">{{ link.author.name }}</a>{% endif %}
</div>
{% endfor %}
</div>

View file

@ -34,13 +34,13 @@ schema: music-index
</h3>
<div class="track-display">
<input id="tracks-recent" name="track-options" type="radio" aria-hidden="true" checked />
<input id="tracks-window" name="track-options" type="radio" aria-hidden="true" />
<input id="tracks-chart" name="track-options" type="radio" aria-hidden="true" />
<label for="tracks-recent" class="button" data-toggle="tracks-recent">Recent</label>
<label for="tracks-window" class="button" data-toggle="tracks-window">This week</label>
<label for="tracks-chart" class="button" data-toggle="tracks-chart">This week</label>
<div class="tracks-recent">
{% render "partials/media/music/recent", data:music.recent %}
</div>
<div class="tracks-window">
<div class="tracks-chart">
{% render "partials/media/music/chart.liquid", data:music.week.tracks, mostPlayed:music.week.tracks[0].plays, count: 10 %}
</div>
</div>

View file

@ -6,7 +6,7 @@ pagination:
alias: page
description: "{{ page.description }}"
permalink: "{{ page.permalink }}/index.html"
image: "{{ page.open_graph_image | prepend: 'https://cdn.coryd.dev/' | default: globals.meta_data.opengraph_default }}"
image: "{{ page.open_graph_image | prepend: 'https://cdn.coryd.dev' | default: globals.avatar }}"
updated: {{ page.updated | default: null }}
---
{% render "partials/blocks/index.liquid", blocks:page.blocks, collections:collections, links:links %}
{% render "partials/blocks/index.liquid", blocks:page.blocks %}

View file

@ -6,7 +6,7 @@ pagination:
data: movies.favorites
size: 24
permalink: "/watching/favorite-movies/{% if pagination.pageNumber > 0 %}{{ pagination.pageNumber }}/{% endif %}index.html"
schema: watching
schema: favorite-movies
---
<a class="icon-link" href="/watching" title="Go back to the watching index page">{% tablericon "arrow-left" %} Back to watching</a>
{% if pagination.pageNumber == 0 %}

View file

@ -6,7 +6,7 @@ pagination:
data: tv.favorites
size: 24
permalink: "/watching/favorite-shows/{% if pagination.pageNumber > 0 %}{{ pagination.pageNumber }}/{% endif %}index.html"
schema: watching
schema: favorite-shows
---
<a class="icon-link" href="/watching" title="Go back to the watching index page">{% tablericon "arrow-left" %} Back to watching</a>
{% if pagination.pageNumber == 0 %}

View file

@ -32,7 +32,7 @@ schema: watching
Favorite movies
</a>
</h3>
{% assign favoriteMovies = movies.favorites | featuredWatching: 6 %}
{% assign favoriteMovies = movies.favorites | shuffleArray | featuredWatching: 6 %}
{% render "partials/media/watching/grid.liquid", mediaItems:favoriteMovies, count: 6 %}
<h3 id="favorite-shows">
<a class="icon-link" href="/watching/favorite-shows">
@ -40,5 +40,5 @@ schema: watching
Favorite shows
</a>
</h3>
{% assign favoriteShows = tv.favorites | featuredWatching: 6 %}
{% assign favoriteShows = tv.favorites | shuffleArray | featuredWatching: 6 %}
{% render "partials/media/watching/grid.liquid", mediaItems:favoriteShows, count: 6 %}

View file

@ -6,7 +6,7 @@ pagination:
data: tv.recentlyWatched
size: 24
permalink: "/watching/recent/shows/{% if pagination.pageNumber > 0 %}{{ pagination.pageNumber }}/{% endif %}index.html"
schema: watching
schema: watching-shows
---
<a class="icon-link" href="/watching" title="Go back to the watching index page">{% tablericon "arrow-left" %} Back to watching</a>
{% if pagination.pageNumber == 0 %}

View file

@ -10,7 +10,6 @@ schema: show
{%- capture alt -%}
{{ show.title }} / {{ show.year }}
{%- endcapture -%}
{% assign lastWatched = show | getLastWatched %}
<a class="icon-link" href="/watching" title="Go back to the watching index page">{% tablericon "arrow-left" %} Back to watching</a>
<article class="watching-focus">
<img
@ -41,13 +40,9 @@ schema: show
{%- if show.collected -%}
<p class="sub-meta collected">{% tablericon "circle-check" %} This show is in my collection!</p>
{%- endif -%}
{%- if lastWatched -%}
{%- if show.episode.formatted_episode -%}
{%- capture lastWatchedText -%}
{%- if show.episodes -%}
I last watched <strong class="highlight-text">{{ show.episodes | lastWatchedEpisode }}</strong> on {{ lastWatched | date: "%B %e, %Y" }}.
{%- else -%}
Last watched on {{ lastWatched | date: "%B %e, %Y" }}.
{%- endif -%}
I last watched <strong class="highlight-text">{{ show.episode.formatted_episode }}</strong> on {{ show.episode.last_watched_at | date: "%B %e, %Y" }}.
{%- endcapture -%}
<p class="sub-meta">{{ lastWatchedText }}</p>
{%- endif -%}

View file

@ -9,6 +9,6 @@ permalink: "/feeds/album-releases.json"
title:"Album releases / Cory Dransfeldt"
globals:globals
data:releases
updated:releases[0].release_date
updated:releases[0].releaseDate
appVersion:appVersion
%}

View file

@ -3,7 +3,7 @@ layout: null
eleventyExcludeFromCollections: true
permalink: "/feeds/books.json"
---
{%- assign bookData = books.all | bookStatus: 'finished' | bookSortDescending -%}
{%- assign bookData = books.all | bookStatus: 'finished' -%}
{% render "partials/feeds/json.liquid"
permalink:"/feeds/books"
title:"Books / Cory Dransfeldt"

View file

@ -9,5 +9,5 @@ permalink: "/feeds/album-releases"
title:"Album releases / Cory Dransfeldt"
globals:globals
data:releases
updated:releases[0].release_date
updated:releases[0].releaseDate
%}

View file

@ -3,7 +3,7 @@ layout: null
eleventyExcludeFromCollections: true
permalink: "/feeds/books"
---
{%- assign bookData = books.all | bookStatus: 'finished' | bookSortDescending -%}
{%- assign bookData = books.all | bookStatus: 'finished' -%}
{% render "partials/feeds/rss.liquid"
permalink:"/feeds/books"
title:"Books / Cory Dransfeldt"