From c6d00b2836ec2f20a9e28d84abffbf2fbff91287 Mon Sep 17 00:00:00 2001 From: Cory Dransfeldt Date: Fri, 11 Oct 2024 19:10:20 -0700 Subject: [PATCH] feat: feed/search/sitemap --- .eleventy.js | 14 +- config/collections/index.js | 192 +----------------- config/filters/dates.js | 22 +- config/filters/feeds.js | 80 -------- config/filters/index.js | 2 - config/filters/media.js | 2 +- package-lock.json | 93 +-------- package.json | 3 +- src/data/activity.js | 19 ++ src/data/albumReleases.js | 3 +- src/data/books.js | 17 +- src/data/movies.js | 13 +- src/data/search.js | 19 ++ src/data/sitemap.js | 19 ++ src/data/syndication.js | 19 ++ src/includes/partials/feeds/json.liquid | 68 ++----- src/includes/partials/feeds/rss.liquid | 25 +-- .../partials/feeds/syndication.rss.liquid | 29 +++ src/pages/data/search.json.liquid | 4 +- src/pages/feeds/json/album-releases.liquid | 14 -- src/pages/feeds/json/all.liquid | 5 +- src/pages/feeds/json/books.liquid | 9 +- src/pages/feeds/json/links.liquid | 4 +- src/pages/feeds/json/movies.liquid | 8 +- src/pages/feeds/json/posts.liquid | 6 +- src/pages/feeds/rss/album-releases.liquid | 13 -- src/pages/feeds/rss/all.liquid | 3 +- src/pages/feeds/rss/books.liquid | 4 +- src/pages/feeds/rss/links.liquid | 1 - src/pages/feeds/rss/movies.liquid | 3 +- src/pages/feeds/rss/posts.liquid | 1 - src/pages/feeds/rss/syndication.liquid | 11 + src/pages/meta/sitemap.liquid | 6 +- workers/mastodon/index.js | 2 +- 34 files changed, 198 insertions(+), 535 deletions(-) delete mode 100644 config/filters/feeds.js create mode 100644 src/data/activity.js create mode 100644 src/data/search.js create mode 100644 src/data/sitemap.js create mode 100644 src/data/syndication.js create mode 100644 src/includes/partials/feeds/syndication.rss.liquid delete mode 100644 src/pages/feeds/json/album-releases.liquid delete mode 100644 src/pages/feeds/rss/album-releases.liquid create mode 100644 src/pages/feeds/rss/syndication.liquid diff --git a/.eleventy.js b/.eleventy.js index 998faa12..ca40a2ee 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -9,7 +9,7 @@ import markdownItPrism from 'markdown-it-prism' import syntaxHighlight from '@11ty/eleventy-plugin-syntaxhighlight' import tablerIcons from '@cdransf/eleventy-plugin-tabler-icons' import { copyErrorPages, minifyJsComponents } from './config/events/index.js' -import { processContent, albumReleasesCalendar } from './config/collections/index.js' +import { albumReleasesCalendar } from './config/collections/index.js' import { cssConfig } from './config/plugins/css-config.js' // load .env @@ -52,18 +52,6 @@ export default async function (eleventyConfig) { 'node_modules/youtube-video-element/youtube-video-element.js': 'assets/scripts/components/youtube-video-element.js' }) - eleventyConfig.addCollection('allContent', (collection) => { - const { allContent } = processContent(collection) - return allContent - }) - eleventyConfig.addCollection('searchIndex', (collection) => { - const { searchIndex } = processContent(collection) - return searchIndex - }) - eleventyConfig.addCollection('siteMap', (collection) => { - const { siteMap } = processContent(collection) - return siteMap - }) eleventyConfig.addCollection('albumReleasesCalendar', albumReleasesCalendar) const md = markdownIt({ html: true, linkify: true }) diff --git a/config/collections/index.js b/config/collections/index.js index f77043c3..cde79213 100644 --- a/config/collections/index.js +++ b/config/collections/index.js @@ -1,196 +1,6 @@ import { DateTime } from 'luxon' -import markdownIt from 'markdown-it' import ics from 'ics' -const BASE_URL = 'https://coryd.dev' -const md = markdownIt() - -const normalizeWord = (word) => { - if (!word) return '' - const wordMap = { - 'ai': 'AI', - 'css': 'CSS', - 'ios': 'iOS', - 'javascript': 'JavaScript', - 'macos': 'macOS', - 'tv': 'TV' - } - return wordMap[word?.toLowerCase()] || word?.charAt(0).toUpperCase() + word.slice(1) -} - -const tagsToHashtags = (item) => { - const tags = item?.['tags'] || [] - if (tags.length) return tags.map(tag => '#' + normalizeWord(tag)).join(' ') - return '' -} - -export const processContent = (collection) => { - const siteMapContent = [] - const searchIndex = [] - const aggregateContent = [] - let id = 0 - - const collectionData = collection.getAll()[0] - const { data } = collectionData - const { posts, links, movies, books, pages, artists, genres, tv, concerts, albumReleases } = data - - const parseDate = (date) => { - if (!date) return null - - const formats = [ - { method: 'fromISO' }, - { method: 'fromFormat', format: 'yyyy-MM-dd' }, - { method: 'fromFormat', format: 'MM/dd/yyyy' }, - { method: 'fromFormat', format: 'dd-MM-yyyy' } - ] - - for (const { method, format } of formats) { - const parsedDate = format - ? DateTime[method](date, format) - : DateTime[method](date) - - if (parsedDate.isValid) return parsedDate - } - - return null - } - - const absoluteUrl = (url) => new URL(url, BASE_URL).toString() - const isValidUrl = (url) => { - try { - new URL(url) - return true - } catch { - return false - } - } - - const addSiteMapContent = (items, getTitle, getDate) => { - const addedUrls = new Set() - - if (items) { - items.forEach((item) => { - let url = item?.['permalink'] || item?.['url'] - - if (!url || addedUrls.has(url)) return - if (!isValidUrl(url)) url = absoluteUrl(url) - if (addedUrls.has(url)) return - - const parsedDate = getDate ? parseDate(getDate(item)) : null - const formattedDate = parsedDate ? parsedDate.toFormat("yyyy-MM-dd'T'HH:mm:ssZZ") : null - const content = { - url, - title: getTitle(item), - date: formattedDate - } - - siteMapContent.push(content) - addedUrls.add(url) - }) - } - } - - const addItemToIndex = (items, icon, getUrl, getTitle, getTags) => { - if (items) { - items.forEach((item) => { - const url = getUrl(item) - if (!url) return - - const absoluteUrlString = isValidUrl(url) ? url : absoluteUrl(url) - searchIndex.push({ - id, - url: absoluteUrlString, - title: `${icon}: ${getTitle(item)}`, - tags: getTags ? getTags(item) : [] - }) - id++ - }) - } - } - - const addContent = (items, icon, getTitle, getDate) => { - if (items) { - items.forEach((item) => { - let attribution = '' - let hashTags = tagsToHashtags(item) ? ' ' + tagsToHashtags(item) : '' - if (item['type'] === 'album-release') hashTags = ' #Music #NewMusic' - if (item['type'] === 'concert') hashTags = ' #Music #Concert' - - if (item?.['author']?.['mastodon']) { - const mastoUrl = new URL(item['author']['mastodon']) - attribution = `${mastoUrl.pathname.replace('/', '')}@${mastoUrl.host}` - } else if (item?.['author']?.['name']) { - attribution = item['author']['name'] - } - - let url = item['url'] || item['link'] - if (url && !isValidUrl(url)) url = absoluteUrl(url) - if (item['type'] === 'concert') url = `${item['artist']?.['url'] ? item['artist']['url'] : BASE_URL + '/music/concerts'}?t=${DateTime.fromISO(item['date']).toMillis()}${item['artist']?.['url'] ? '#concerts' : ''}` - - const content = { - url, - title: `${icon}: ${getTitle(item)}${attribution ? ' via ' + attribution : ''}${hashTags}`, - type: item['type'] - } - - if (item['description']) { - content['description'] = md.render(item['description']) - } else if (item['notes']) { - content['notes'] = md.render(item['notes']) - } else { - content['description'] = '' - } - - const date = getDate ? parseDate(getDate(item)) : null - if (date) content['date'] = date - - aggregateContent.push(content) - }) - } - } - - const movieData = movies['movies'].filter((movie) => movie['rating']) - const showData = tv['shows'].filter((show) => show?.['episode']?.['formatted_episode']) - const bookData = books['all'].filter((book) => book['rating']) - - addItemToIndex(posts, '📝', (item) => item['url'], (item) => item['title'], (item) => item['tags']) - addItemToIndex(links, '🔗', (item) => item['link'], (item) => item['title'], (item) => item['tags']) - addItemToIndex(artists, '🎙️', (item) => item['url'], (item) => `${item['name']} (${item['country']}) - ${item['genre']?.['name']}`, (item) => `['${item['genre']}']`) - addItemToIndex(genres, '🎵', (item) => item['url'], (item) => item['name'], (item) => item.artists.map(artist => artist['name_string'])) - if (movieData) addItemToIndex(movieData, '🎥', (item) => item['url'], (item) => `${item['title']} (${item['rating']})`, (item) => item['tags']) - if (showData) addItemToIndex(showData, '📺', (item) => item['url'], (item) => `${item['title']} (${item['year']})`, (item) => item['tags']) - if (bookData) addItemToIndex(bookData, '📖', (item) => item['url'], (item) => `${item['title']} (${item['rating']})`, (item) => item['tags']) - - addContent(posts, '📝', (item) => item['title'], (item) => item['date']) - addContent(links, '🔗', (item) => item['title'], (item) => item['date']) - addContent(books.all.filter((book) => book['status'] === 'finished'), '📖', (item) => `${item['title']}${item['rating'] ? ' (' + item['rating'] + ')' : ''}`, (item) => item['date']) - addContent(movies['movies'], '🎥', (item) => `${item['title']}${item['rating'] ? ' (' + item['rating'] + ')' : ''}`, (item) => item['lastWatched']) - addContent(concerts, '🎤', (item) => `${item['artistNameString'] ? item['artistNameString'] : item['artist']['name']} at ${item['venue']['name'].split(',')[0].trim()}`, (item) => item['date']) - addContent([...albumReleases['current']].reverse(), '📆', (item) => `${item['title']} by ${item['artist']['name']}`, (item) => item['release_date']) - - addSiteMapContent(posts, (item) => item['title'], (item) => item['date']) - addSiteMapContent(pages, (item) => item['title'], (item) => item['date']) - addSiteMapContent(artists, (item) => item['name'], (item) => item['date']) - addSiteMapContent(genres, (item) => item['name'], (item) => item['date']) - addSiteMapContent(movies['movies'], (item) => item['title'], (item) => item['date']) - addSiteMapContent(books.all, (item) => item['title'], (item) => item['date']) - addSiteMapContent(tv?.['shows'], (item) => item['title'], (item) => item['date']) - - return { - searchIndex, - allContent: aggregateContent.sort((a, b) => { - const dateA = a['date'] ? DateTime.fromISO(a['date']) : DateTime.fromMillis(0) - const dateB = b['date'] ? DateTime.fromISO(b['date']) : DateTime.fromMillis(0) - return dateB - dateA - }), - siteMap: siteMapContent.sort((a, b) => { - const dateA = a['date'] ? DateTime.fromISO(a['date']) : DateTime.fromMillis(0) - const dateB = b['date'] ? DateTime.fromISO(b['date']) : DateTime.fromMillis(0) - return dateB - dateA - }) - } -} - export const albumReleasesCalendar = (collection) => { const collectionData = collection.getAll()[0] const { data } = collectionData @@ -198,7 +8,7 @@ export const albumReleasesCalendar = (collection) => { if (!all || all.length === 0) return '' const events = all.map(album => { - const date = DateTime.fromFormat(album['date'], 'MMMM d, yyyy') + const date = DateTime.fromISO(album['release_date']) if (!date.isValid) return null return { diff --git a/config/filters/dates.js b/config/filters/dates.js index 446d0e85..5aedb0dd 100644 --- a/config/filters/dates.js +++ b/config/filters/dates.js @@ -16,22 +16,24 @@ export default { return DateTime.now().diff(DateTime.fromJSDate(new Date(date)), 'years').years > 3 }, stringToRFC822Date: (dateString) => { - const addLeadingZero = (num) => { - num = num.toString() - while (num.length < 2) num = '0' + num - return num - } + const date = new Date(Date.parse(dateString)) const dayStrings = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] const monthStrings = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] - const timeStamp = Date.parse(dateString) - const date = new Date(timeStamp) const day = dayStrings[date.getDay()] - const dayNumber = addLeadingZero(date.getDate()) + const dayNumber = String(date.getDate()).padStart(2, '0') const month = monthStrings[date.getMonth()] const year = date.getFullYear() - const time = `${addLeadingZero(date.getHours())}:${addLeadingZero(date.getMinutes())}:00` + const time = `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}:00` const timezone = date.getTimezoneOffset() === 0 ? 'GMT' : 'PT' - return `${day}, ${dayNumber} ${month} ${year} ${time} ${timezone}` + }, + stringToRFC3339: (dateString) => { + const timestamp = Date.parse(dateString); + if (!isNaN(timestamp)) { + const date = new Date(timestamp) + return date.toISOString() + } else { + return ''; + } } } \ No newline at end of file diff --git a/config/filters/feeds.js b/config/filters/feeds.js deleted file mode 100644 index 5b6756bc..00000000 --- a/config/filters/feeds.js +++ /dev/null @@ -1,80 +0,0 @@ -import { URL } from 'url' -import markdownIt from 'markdown-it' -import markdownItAnchor from 'markdown-it-anchor' -import markdownItFootnote from 'markdown-it-footnote' -import sanitizeHtml from 'sanitize-html' -import truncate from 'truncate-html' - -const BASE_URL = 'https://coryd.dev' - -export default { - normalizeEntries: (entries, limit) => { - const posts = [] - const mdGenerator = () => { - const md = markdownIt({ html: true, linkify: true }) - md.use(markdownItAnchor, { - level: [1, 2], - permalink: markdownItAnchor['permalink']['headerLink']({ safariReaderFix: true }) - }) - md.use(markdownItFootnote) - md.renderer['rules']['footnote_ref'] = (tokens, idx) => `${tokens[idx]['meta']['id'] + 1}` - md.renderer['rules']['footnote_block_open'] = () => '
\n
\n
    \n' - md.renderer['rules']['footnote_open'] = (tokens, idx) => `
  1. ` - md.renderer['rules']['footnote_anchor'] = () => '' - - return md - } - - const entryData = limit ? entries.slice(0, limit) : entries - entryData.forEach((entry) => { - const md = mdGenerator() - const dateKey = Object.keys(entry).find(key => key.includes('date')) - const { - artist, author, backdrop, content, description, image, link, rating, review, - slug, title, url, tags, type - } = entry - - const processedEntry = { - title: title.trim(), - date: new Date(entry[dateKey]), - content: description || '' - } - const feedNote = '

    This is a full text feed, but not all content can be rendered perfectly within the feed. If something looks off, feel free to visit my site for the original post.

    ' - - processedEntry['url'] = (url?.includes('http')) ? url : new URL(slug || url, BASE_URL).toString() - - if (link) { - processedEntry['title'] = `${title} via ${author?.['name'] || 'Unknown'}` - processedEntry['url'] = link - processedEntry['author'] = { - name: author?.['name'] || 'Unknown', - url: author?.['url'] || '', - mastodon: author?.['mastodon'] || '', - rss: author?.['rss_feed'] || '' - } - processedEntry['excerpt'] = sanitizeHtml(md.render(description || '')) - } else if (['book', 'movie'].includes(type)) { - processedEntry['excerpt'] = sanitizeHtml(md.render(review || description || '')) - } else if (type === 'album-release') { - let sanitizedDescription = sanitizeHtml(md.render(description || '')) - let truncatedDescription = truncate(sanitizedDescription, { length: 500, reserveLastWord: true, ellipsis: '...' }) - if (artist?.['name'] && artist?.['url'] && sanitizedDescription.length > 500) truncatedDescription += `

    Read more about ${artist['name']}

    ` - processedEntry['excerpt'] = truncatedDescription - } else if (slug && content) { - processedEntry['excerpt'] = sanitizeHtml(md.render(content) + feedNote, { disallowedTagsMode: 'completelyDiscard' }) - } else if (description) { - processedEntry['excerpt'] = description - } - - processedEntry['image'] = backdrop || image - - if (rating) processedEntry['rating'] = rating - if (tags) processedEntry['tags'] = tags - if (type === 'album-release' && artist) processedEntry['title'] = `${title} by ${artist['name']}` - - posts.push(processedEntry) - }) - - return posts - } -} \ No newline at end of file diff --git a/config/filters/index.js b/config/filters/index.js index f497d7ad..94a6a2cf 100644 --- a/config/filters/index.js +++ b/config/filters/index.js @@ -1,12 +1,10 @@ import dates from './dates.js' -import feeds from './feeds.js' import general from './general.js' import media from './media.js' import navigation from './navigation.js' export default { ...dates, - ...feeds, ...general, ...media, ...navigation, diff --git a/config/filters/media.js b/config/filters/media.js index 69cbc6fb..d7db2a5e 100644 --- a/config/filters/media.js +++ b/config/filters/media.js @@ -27,7 +27,7 @@ export default { break case 'album-release': normalized.alt = `${item['title']} by ${item['artist']['name']}` - normalized.subtext = `${item['artist']['name']} / ${item['date']}` + normalized.subtext = `${item['artist']['name']} / ${item['release_date_formatted']}` break case 'movie': normalized.alt = item['title'] diff --git a/package-lock.json b/package-lock.json index 8e83cbbf..a5293dcd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,8 +42,7 @@ "rimraf": "^6.0.1", "sanitize-html": "^2.13.1", "slugify": "^1.6.6", - "terser": "^5.34.1", - "truncate-html": "^1.1.2" + "terser": "^5.34.1" } }, "node_modules/@11ty/dependency-tree": { @@ -1120,46 +1119,6 @@ "dev": true, "license": "MIT" }, - "node_modules/cheerio": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -3262,46 +3221,6 @@ "dev": true, "license": "MIT" }, - "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", - "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "domhandler": "^5.0.2", - "parse5": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/parseley": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz", @@ -4981,16 +4900,6 @@ "dev": true, "license": "MIT" }, - "node_modules/truncate-html": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/truncate-html/-/truncate-html-1.1.2.tgz", - "integrity": "sha512-BiLzO594/Quf0wu3jHnVxHA4X5tl4Gunhqe2mlGTa5ElwHJGw7M/N5JdBvU8OPtR+MaEIvmyUdNxnoEi3YI5Yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cheerio": "1.0.0-rc.12" - } - }, "node_modules/tslib": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", diff --git a/package.json b/package.json index 4bae8c1e..a3cce6ca 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,6 @@ "rimraf": "^6.0.1", "sanitize-html": "^2.13.1", "slugify": "^1.6.6", - "terser": "^5.34.1", - "truncate-html": "^1.1.2" + "terser": "^5.34.1" } } diff --git a/src/data/activity.js b/src/data/activity.js new file mode 100644 index 00000000..97f69c8b --- /dev/null +++ b/src/data/activity.js @@ -0,0 +1,19 @@ +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) + +export default async function fetchSyndication() { + const { data, error } = await supabase + .from('optimized_all_activity') + .select('feed') + + if (error) { + console.error('Error fetching search index data:', error) + return [] + } + + const [{ feed } = {}] = data + return feed?.filter(item => item['feed'] !== null) || [] +} \ No newline at end of file diff --git a/src/data/albumReleases.js b/src/data/albumReleases.js index b265e935..94d3a8c4 100644 --- a/src/data/albumReleases.js +++ b/src/data/albumReleases.js @@ -29,9 +29,8 @@ const fetchAlbumReleases = async () => { }).sort((a, b) => a['timestamp'] - b['timestamp']) const upcoming = all.filter(album => album['release_timestamp'] > today) - const current = all.filter(album => album['release_timestamp'] <= today) - return { all, upcoming, current } + return { all, upcoming } } export default async function () { diff --git a/src/data/books.js b/src/data/books.js index 0642e57c..fdf8345b 100644 --- a/src/data/books.js +++ b/src/data/books.js @@ -29,18 +29,6 @@ const fetchAllBooks = async () => { return books } -const processBooks = (books) => { - return books.map(book => { - const dateFinished = book['date_finished'] ? new Date(book['date_finished']) : null - const year = dateFinished && !isNaN(dateFinished.getTime()) ? dateFinished.getUTCFullYear() : null - - return { - ...book, - year, - } - }) -} - const sortBooksByYear = (books) => { const years = {} books.forEach(book => { @@ -51,12 +39,11 @@ const sortBooksByYear = (books) => { years[year]['data'].push(book) } }) - return Object.values(years).filter(year => year.value > 2017) + return Object.values(years).filter(year => year['value'] > 2017) } export default async function () { const books = await fetchAllBooks() - const processedBooks = processBooks(books) - return { all: processedBooks, years: sortBooksByYear(processedBooks) } + return { all: books, years: sortBooksByYear(books), feed: books.filter(book => book['feed']) } } \ No newline at end of file diff --git a/src/data/movies.js b/src/data/movies.js index 981a1ea0..343a1238 100644 --- a/src/data/movies.js +++ b/src/data/movies.js @@ -35,15 +35,15 @@ export default async function () { try { const movies = await fetchAllMovies() - 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) + const favoriteMovies = movies.filter(movie => movie['favorite']) + const recentlyWatchedMovies = movies.filter(movie => movie['last_watched'] && year - DateTime.fromISO(movie['last_watched']).year <= 3) return { movies, - watchHistory: filterMovies(movie => movie.last_watched), + watchHistory: movies.filter(movie => movie['last_watched']), recentlyWatched: recentlyWatchedMovies, - favorites: favoriteMovies.sort((a, b) => a.title.localeCompare(b.title)), + favorites: favoriteMovies.sort((a, b) => a['title'].localeCompare(b['title'])), + feed: movies.filter(movie => movie['feed']), } } catch (error) { console.error('Error fetching and processing movies data:', error) @@ -51,7 +51,8 @@ export default async function () { movies: [], watchHistory: [], recentlyWatched: [], - favorites: [] + favorites: [], + feed: [] } } } \ No newline at end of file diff --git a/src/data/search.js b/src/data/search.js new file mode 100644 index 00000000..006b4c7e --- /dev/null +++ b/src/data/search.js @@ -0,0 +1,19 @@ +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) + +export default async function fetchSearchIndex() { + const { data, error } = await supabase + .from('optimized_search_index') + .select('search_index') + + if (error) { + console.error('Error fetching search index data:', error) + return [] + } + + const [{ search_index } = {}] = data + return search_index || [] +} \ No newline at end of file diff --git a/src/data/sitemap.js b/src/data/sitemap.js new file mode 100644 index 00000000..00b702a4 --- /dev/null +++ b/src/data/sitemap.js @@ -0,0 +1,19 @@ +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) + +export default async function fetchSitemap() { + const { data, error } = await supabase + .from('optimized_sitemap') + .select('sitemap') + + if (error) { + console.error('Error fetching sitemap data:', error) + return [] + } + + const [{ sitemap } = {}] = data + return sitemap || [] +} diff --git a/src/data/syndication.js b/src/data/syndication.js new file mode 100644 index 00000000..57a09edd --- /dev/null +++ b/src/data/syndication.js @@ -0,0 +1,19 @@ +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) + +export default async function fetchSyndication() { + const { data, error } = await supabase + .from('optimized_syndication') + .select('syndication') + + if (error) { + console.error('Error fetching search index data:', error) + return [] + } + + const [{ syndication } = {}] = data + return syndication?.filter(item => item['syndication'] !== null) || [] +} \ No newline at end of file diff --git a/src/includes/partials/feeds/json.liquid b/src/includes/partials/feeds/json.liquid index 458bbf42..255ec952 100644 --- a/src/includes/partials/feeds/json.liquid +++ b/src/includes/partials/feeds/json.liquid @@ -1,48 +1,24 @@ { - "version": "https://jsonfeed.org/version/1.1", - "title": "{{ title | escape }}", - "home_page_url": "{{ permalink | absoluteUrl | escape }}", - "feed_url": "{{ permalink | absoluteUrl | escape }}.json", - "description": "{{ globals.site_description | escape }}", - "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 %}" - }], - "items": [ - {%- assign entries = data | normalizeEntries: 20 -%} - {%- for entry in entries -%} - {%- assign summary = entry.content | strip_html | normalize_whitespace | escape -%} - {%- assign utm_parameters = "utm_source=rss&utm_medium=feed&utm_campaign=" | append: utm_campaign -%} - { - "id": "{{ entry.url | encodeAmp | escape }}", - "title": "{{ entry.title | escape }}{% if entry.authors %} via {{ entry.authors.name | escape }}{% endif %}{% if entry.rating %} ({{ entry.rating | escape }}){% endif %}", - {%- if utm_campaign -%} - "url": "{{ entry.url | append: '?' | append: utm_parameters }}", - {%- else -%} - "url": "{{ entry.url | encodeAmp }}", - {%- endif -%} - "content_html": "{{ summary }}", - "summary": "{{ summary }}", - {%- if entry.author -%} - "external_url": "{{ entry.url | encodeAmp | escape }}", - "authors": [{ - "name": "{{ entry.author.name | escape }}", - "url": "{{ entry.author.url | escape }}", - "mastodon": "{{ entry.author.mastodon | escape }}", - "rss": "{{ entry.author.feed | escape }}" - }], - {%- endif %} - "date_published": "{{ entry.date | date: '%Y-%m-%dT%H:%M:%S%:z' }}"{%- if entry.tags -%}, - "tags": [ - {%- for tag in entry.tags -%} - "{{ tag | escape }}"{%- unless forloop.last -%}, {% endunless -%} - {%- endfor -%} - ] - {%- endif -%} - }{%- if forloop.last == false -%},{%- endif -%} - {%- endfor -%} - ] + "version": "https://jsonfeed.org/version/1", + "title": "{{ title }}", + "home_page_url": "{{ globals.url }}", + "feed_url": "{{ permalink | absoluteUrl }}", + "description": "{{ globals.site_description }}", + "icon": "https://cdn.coryd.dev{{ globals.avatar }}?class=w200", + "author": { + "name": "{{ globals.site_name }}", + "url": "{{ globals.url }}", + "avatar": "https://cdn.coryd.dev{{ globals.avatar }}?class=w200" + }, + "items": [ + {%- assign entries = data -%} + {%- for entry in entries limit: 20 -%} + { + "id": "{{ entry.feed.url | encodeAmp }}", + "url": "{{ entry.feed.url | encodeAmp }}", + "title": "{{ entry.feed.title }}", + "date_published": "{{ entry.feed.date | stringToRFC3339 }}" + }{%- if forloop.last == false -%},{%- endif -%} + {%- endfor -%} + ] } \ No newline at end of file diff --git a/src/includes/partials/feeds/rss.liquid b/src/includes/partials/feeds/rss.liquid index fd4c39e4..42a8e565 100644 --- a/src/includes/partials/feeds/rss.liquid +++ b/src/includes/partials/feeds/rss.liquid @@ -3,11 +3,11 @@ - {%- assign entries = data | normalizeEntries: 20 -%} + {%- assign entries = data -%} <![CDATA[{{ title }}]]> {{ permalink | absoluteUrl }} - {{ updated | stringToRFC822Date }} + {{ 'now' | date: "%a, %d %b %Y %H:%M:%S %z" }} <![CDATA[{{ title }}]]> {{ permalink | absoluteUrl }} @@ -15,27 +15,28 @@ 144 144 - {% for entry in entries -%} + {% for entry in entries limit: 20 -%} + {%- assign entryFeed = entry.feed -%} {%- assign rating = entry.rating -%} {%- capture entryTitle -%} - {{ entry.title }} - {%- if entry.authors %} via {{ entry.authors.name }}{%- endif -%} + {{ entryFeed.title }} + {%- if entryFeed.artist and entryFeed.artist.name %} via {{ entryFeed.artist.name }}{%- endif -%} {%- if rating %} ({{ rating }}){%- endif -%} {%- endcapture -%} {%- assign utm_parameters = "utm_source=rss&utm_medium=feed&utm_campaign=" | append: utm_campaign -%} <![CDATA[{{ entryTitle }}]]> {%- if utm_campaign -%} - {{ entry.url | append: '?' | append: utm_parameters | encodeAmp }} + {{ entryFeed.url | append: '?' | append: utm_parameters | encodeAmp }} {%- else -%} - {{ entry.url | encodeAmp }} + {{ entryFeed.url | encodeAmp }} {%- endif -%} - {{ entry.date | stringToRFC822Date }} - {{ entry.url | encodeAmp }} - {%- if entry.image -%} - + {{ entryFeed.date | stringToRFC822Date }} + {{ entryFeed.url | encodeAmp }} + {%- if entryFeed.image -%} + {%- endif -%} - {{ entry.excerpt | escape }} + {%- endfor %} diff --git a/src/includes/partials/feeds/syndication.rss.liquid b/src/includes/partials/feeds/syndication.rss.liquid new file mode 100644 index 00000000..37386f49 --- /dev/null +++ b/src/includes/partials/feeds/syndication.rss.liquid @@ -0,0 +1,29 @@ + + + + + {%- assign entries = data -%} + <![CDATA[{{ title }}]]> + + {{ permalink | absoluteUrl }} + {% assign firstEntry = entries | first %} + {{ 'now' | date: "%a, %d %b %Y %H:%M:%S %z" }} + + <![CDATA[{{ title }}]]> + {{ permalink | absoluteUrl }} + {{ "https://cdn.coryd.dev" | append: globals.avatar | append: "?class=w200" }} + 144 + 144 + + {% for entry in entries limit: 20 -%} + {%- assign entrySyndication = entry.syndication -%} + + <![CDATA[{{ entrySyndication.title }}]]> + {{ entrySyndication.url | encodeAmp }} + {{ entrySyndication.date | stringToRFC822Date }} + {{ entrySyndication.url | encodeAmp }} + + + {%- endfor %} + + \ No newline at end of file diff --git a/src/pages/data/search.json.liquid b/src/pages/data/search.json.liquid index 7c1e1e26..ae4ac018 100644 --- a/src/pages/data/search.json.liquid +++ b/src/pages/data/search.json.liquid @@ -1,4 +1,4 @@ --- -permalink: /api/search +permalink: "/api/search" --- -{{ collections.searchIndex | json }} \ No newline at end of file +{{ search | json }} \ No newline at end of file diff --git a/src/pages/feeds/json/album-releases.liquid b/src/pages/feeds/json/album-releases.liquid deleted file mode 100644 index ec953837..00000000 --- a/src/pages/feeds/json/album-releases.liquid +++ /dev/null @@ -1,14 +0,0 @@ ---- -layout: null -eleventyExcludeFromCollections: true -permalink: "/feeds/album-releases.json" ---- -{%- assign releases = albumReleases.current | reverse -%} -{% render "partials/feeds/json.liquid" - permalink:"/feeds/album-releases.json" - title:"Album releases / Cory Dransfeldt" - globals:globals - data:releases - updated:releases[0].releaseDate - appVersion:appVersion -%} \ No newline at end of file diff --git a/src/pages/feeds/json/all.liquid b/src/pages/feeds/json/all.liquid index 169ecde9..80771b89 100644 --- a/src/pages/feeds/json/all.liquid +++ b/src/pages/feeds/json/all.liquid @@ -4,10 +4,9 @@ eleventyExcludeFromCollections: true permalink: "/feeds/all.json" --- {% render "partials/feeds/json.liquid" - permalink:"/feeds/all" + permalink:"/feeds/all.json" title:"All activity / Cory Dransfeldt" globals:globals - data:collections.allContent - updated:collections.allContent[0].date + data:activity appVersion:appVersion %} \ No newline at end of file diff --git a/src/pages/feeds/json/books.liquid b/src/pages/feeds/json/books.liquid index d9c8914a..67ebaaf4 100644 --- a/src/pages/feeds/json/books.liquid +++ b/src/pages/feeds/json/books.liquid @@ -3,13 +3,10 @@ layout: null eleventyExcludeFromCollections: true permalink: "/feeds/books.json" --- -{%- assign bookData = books.all | bookStatus: 'finished' -%} {% render "partials/feeds/json.liquid" - permalink:"/feeds/books" + permalink:"/feeds/books.json" title:"Books / Cory Dransfeldt" globals:globals - data:bookData - updated:bookData[0].date - utm_campaign:"books_json_feed" - appVersion:appVersion + data:books.feed + utm_campaign:"books_feed" %} \ No newline at end of file diff --git a/src/pages/feeds/json/links.liquid b/src/pages/feeds/json/links.liquid index 1a780be2..aa7b0d96 100644 --- a/src/pages/feeds/json/links.liquid +++ b/src/pages/feeds/json/links.liquid @@ -4,10 +4,8 @@ eleventyExcludeFromCollections: true permalink: "/feeds/links.json" --- {% render "partials/feeds/json.liquid" - permalink:"/feeds/links" + permalink:"/feeds/links.json" title:"Links / Cory Dransfeldt" globals:globals data:links - updated:links[0].date - appVersion:appVersion %} \ No newline at end of file diff --git a/src/pages/feeds/json/movies.liquid b/src/pages/feeds/json/movies.liquid index bc00588a..a4cceac1 100644 --- a/src/pages/feeds/json/movies.liquid +++ b/src/pages/feeds/json/movies.liquid @@ -4,11 +4,9 @@ eleventyExcludeFromCollections: true permalink: "/feeds/movies.json" --- {% render "partials/feeds/json.liquid" - permalink:"/feeds/movies" + permalink:"/feeds/movies.json" title:"Movies / Cory Dransfeldt" globals:globals - data:movies.recentlyWatched - updated:movies.recentlyWatched[0].lastWatched - utm_campaign:"movies_json_feed" - appVersion:appVersion + data:movies.feed + utm_campaign:"movies_feed" %} \ No newline at end of file diff --git a/src/pages/feeds/json/posts.liquid b/src/pages/feeds/json/posts.liquid index 2e02bd2e..dd4acc3b 100644 --- a/src/pages/feeds/json/posts.liquid +++ b/src/pages/feeds/json/posts.liquid @@ -4,11 +4,9 @@ eleventyExcludeFromCollections: true permalink: "/feeds/posts.json" --- {% render "partials/feeds/json.liquid" - permalink:"/feeds/posts" + permalink:"/feeds/posts.json" title:"Posts / Cory Dransfeldt" globals:globals data:posts - updated:posts[0].date - utm_campaign:"posts_json_feed" - appVersion:appVersion + utm_campaign:"posts_feed" %} \ No newline at end of file diff --git a/src/pages/feeds/rss/album-releases.liquid b/src/pages/feeds/rss/album-releases.liquid deleted file mode 100644 index 639572ea..00000000 --- a/src/pages/feeds/rss/album-releases.liquid +++ /dev/null @@ -1,13 +0,0 @@ ---- -layout: null -eleventyExcludeFromCollections: true -permalink: "/feeds/album-releases" ---- -{%- assign releases = albumReleases.current | reverse -%} -{% render "partials/feeds/rss.liquid" - permalink:"/feeds/album-releases" - title:"Album releases / Cory Dransfeldt" - globals:globals - data:releases - updated:releases[0].releaseDate -%} \ No newline at end of file diff --git a/src/pages/feeds/rss/all.liquid b/src/pages/feeds/rss/all.liquid index 65172ab0..5e07fac9 100644 --- a/src/pages/feeds/rss/all.liquid +++ b/src/pages/feeds/rss/all.liquid @@ -7,6 +7,5 @@ permalink: "/feeds/all" permalink:"/feeds/all" title:"All activity / Cory Dransfeldt" globals:globals - data:collections.allContent - updated:collections.allContent[0].date + data:activity %} \ No newline at end of file diff --git a/src/pages/feeds/rss/books.liquid b/src/pages/feeds/rss/books.liquid index 094b8364..32458ec4 100644 --- a/src/pages/feeds/rss/books.liquid +++ b/src/pages/feeds/rss/books.liquid @@ -3,12 +3,10 @@ layout: null eleventyExcludeFromCollections: true permalink: "/feeds/books" --- -{%- assign bookData = books.all | bookStatus: 'finished' -%} {% render "partials/feeds/rss.liquid" permalink:"/feeds/books" title:"Books / Cory Dransfeldt" globals:globals - data:bookData - updated:bookData[0].date + data:books.feed utm_campaign:"books_feed" %} \ No newline at end of file diff --git a/src/pages/feeds/rss/links.liquid b/src/pages/feeds/rss/links.liquid index 992af611..4061a7bf 100644 --- a/src/pages/feeds/rss/links.liquid +++ b/src/pages/feeds/rss/links.liquid @@ -8,5 +8,4 @@ permalink: "/feeds/links" title:"Links / Cory Dransfeldt" globals:globals data:links - updated:links[0].date %} \ No newline at end of file diff --git a/src/pages/feeds/rss/movies.liquid b/src/pages/feeds/rss/movies.liquid index d243906f..4a3cc24f 100644 --- a/src/pages/feeds/rss/movies.liquid +++ b/src/pages/feeds/rss/movies.liquid @@ -7,7 +7,6 @@ permalink: "/feeds/movies" permalink:"/feeds/movies" title:"Movies / Cory Dransfeldt" globals:globals - data:movies.recentlyWatched - updated:movies.recentlyWatched[0].lastWatched + data:movies.feed utm_campaign:"movies_feed" %} \ No newline at end of file diff --git a/src/pages/feeds/rss/posts.liquid b/src/pages/feeds/rss/posts.liquid index eed1b221..2d4244ea 100644 --- a/src/pages/feeds/rss/posts.liquid +++ b/src/pages/feeds/rss/posts.liquid @@ -8,6 +8,5 @@ permalink: "/feeds/posts" title:"Posts / Cory Dransfeldt" globals:globals data:posts - updated:posts[0].date utm_campaign:"posts_feed" %} \ No newline at end of file diff --git a/src/pages/feeds/rss/syndication.liquid b/src/pages/feeds/rss/syndication.liquid new file mode 100644 index 00000000..f87f7745 --- /dev/null +++ b/src/pages/feeds/rss/syndication.liquid @@ -0,0 +1,11 @@ +--- +layout: null +eleventyExcludeFromCollections: true +permalink: "/feeds/syndication" +--- +{% render "partials/feeds/syndication.rss.liquid" + permalink:"/feeds/syndication" + title:"Syndicated content / Cory Dransfeldt" + globals:globals + data:syndication +%} \ No newline at end of file diff --git a/src/pages/meta/sitemap.liquid b/src/pages/meta/sitemap.liquid index 411ffacc..68c0f740 100644 --- a/src/pages/meta/sitemap.liquid +++ b/src/pages/meta/sitemap.liquid @@ -5,12 +5,12 @@ eleventyExcludeFromCollections: true --- - {% for page in collections.siteMap %} + {% for page in sitemap -%} {{ page.url }} {{ page.date | date: '%Y-%m-%dT%H:%M:%S%:z' }} - {% if page.data.changeFreq %}{{ page.data.changeFreq }}{% else %}monthly{% endif %} - {% if page.data.priority %}{{ page.data.priority }}{% else %}0.5{% endif %} + monthly + 0.5 {% endfor %} \ No newline at end of file diff --git a/workers/mastodon/index.js b/workers/mastodon/index.js index 52b967d6..1e3093a8 100644 --- a/workers/mastodon/index.js +++ b/workers/mastodon/index.js @@ -22,7 +22,7 @@ export default { async function handleMastodonPost(env) { const mastodonApiUrl = 'https://follow.coryd.dev/api/v1/statuses' const accessToken = env.MASTODON_ACCESS_TOKEN - const rssFeedUrl = 'https://coryd.dev/feeds/all' + const rssFeedUrl = 'https://coryd.dev/feeds/syndication' const supabaseUrl = env.SUPABASE_URL const supabaseKey = env.SUPABASE_KEY const supabase = createClient(supabaseUrl, supabaseKey)