chore: clean up config + file structure
This commit is contained in:
parent
d1f8ecd88c
commit
b6fb54ab98
9 changed files with 300 additions and 312 deletions
|
@ -1,44 +0,0 @@
|
|||
const { DateTime } = require('luxon')
|
||||
|
||||
module.exports = {
|
||||
readableDate: (date) => {
|
||||
return DateTime.fromISO(date).toFormat('LLLL d, yyyy')
|
||||
},
|
||||
toDateTime: (date) => {
|
||||
const formatted = DateTime.fromISO(date)
|
||||
|
||||
const trail = (number) => {
|
||||
return parseInt(number, 10) < 10 ? `0${number}` : number
|
||||
}
|
||||
|
||||
return `${formatted.year}-${trail(formatted.month)}-${trail(formatted.day)} ${trail(
|
||||
formatted.hour
|
||||
)}:${trail(formatted.minute)}`
|
||||
},
|
||||
toDateTimeFromUnix: (date) => {
|
||||
const formatted = DateTime.fromSeconds(parseInt(date, 10))
|
||||
|
||||
const trail = (number) => {
|
||||
return parseInt(number, 10) < 10 ? `0${number}` : number
|
||||
}
|
||||
|
||||
return `${trail(formatted.month)}.${trail(formatted.day)}.${formatted.year} ${trail(
|
||||
formatted.hour
|
||||
)}:${trail(formatted.minute)}`
|
||||
},
|
||||
isoDateOnly: (date) => {
|
||||
let d = new Date(date)
|
||||
let month = '' + (d.getMonth() + 1)
|
||||
let day = '' + d.getDate()
|
||||
let year = d.getFullYear()
|
||||
|
||||
if (month.length < 2) month = '0' + month
|
||||
if (day.length < 2) day = '0' + day
|
||||
|
||||
return [month, day, year].join('.')
|
||||
},
|
||||
stringToDate: (string) => {
|
||||
if (!string) return
|
||||
return new Date(string)
|
||||
},
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
const markdownIt = require('markdown-it')
|
||||
|
||||
const { URL } = require('url')
|
||||
const BASE_URL = 'https://coryd.dev'
|
||||
|
||||
module.exports = {
|
||||
normalizeEntries: (entries) => {
|
||||
const md = markdownIt({ html: true, linkify: true })
|
||||
const posts = []
|
||||
entries.forEach((entry) => {
|
||||
const dateKey = Object.keys(entry).find((key) => key.includes('date'))
|
||||
const date = new Date(entry[dateKey])
|
||||
let excerpt = ''
|
||||
|
||||
// set the entry excerpt
|
||||
if (entry.description) excerpt = entry.description
|
||||
if (entry.data?.post_excerpt) excerpt = md.render(entry.data.post_excerpt)
|
||||
|
||||
// if there's a valid entry return a normalized object
|
||||
if (entry)
|
||||
posts.push({
|
||||
title: entry.data?.title || entry.title,
|
||||
url: entry.url.includes('http') ? entry.url : new URL(entry.url, BASE_URL).toString(),
|
||||
content: entry.description,
|
||||
date,
|
||||
excerpt,
|
||||
})
|
||||
})
|
||||
return posts
|
||||
},
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
const marked = require('marked')
|
||||
const sanitizeHTML = require('sanitize-html')
|
||||
|
||||
const utmPattern = /[?&](utm_[^&=]+=[^&#]*)/gi
|
||||
const BASE_URL = 'https://coryd.dev'
|
||||
|
||||
module.exports = {
|
||||
trim: (string, limit) => {
|
||||
return string.length <= limit ? string : `${string.slice(0, limit)}...`
|
||||
},
|
||||
stripIndex: (path) => {
|
||||
return path.replace('/index.html', '/')
|
||||
},
|
||||
mdToHtml: (content) => {
|
||||
return marked.parse(content)
|
||||
},
|
||||
btoa: (string) => {
|
||||
return btoa(string)
|
||||
},
|
||||
dashLower: (string) => string.replace(/\s+/g, '-').toLowerCase(),
|
||||
encodeAmp: (string) => {
|
||||
if (!string) return
|
||||
const pattern = /&(?!(?:[a-zA-Z]+|#[0-9]+|#x[0-9a-fA-F]+);)/g
|
||||
const replacement = '&'
|
||||
return string.replace(pattern, replacement)
|
||||
},
|
||||
stripUtm: (string) => {
|
||||
if (!string) return
|
||||
return string.replace(utmPattern, '')
|
||||
},
|
||||
getPostImage: (image) => {
|
||||
if (image && image !== '') return image
|
||||
return `${BASE_URL}/assets/img/social-card.jpg`
|
||||
},
|
||||
getPopularPosts: (posts, analytics) => {
|
||||
return posts
|
||||
.filter((post) => {
|
||||
if (analytics.find((p) => p.page === post.url)) return true
|
||||
})
|
||||
.sort((a, b) => {
|
||||
const visitors = (page) => analytics.filter((p) => p.page === page.url).pop().visitors
|
||||
return visitors(b) - visitors(a)
|
||||
})
|
||||
},
|
||||
tagLookup: (url, tagMap) => {
|
||||
if (!url) return
|
||||
if (url.includes('thestorygraph.com')) return '#Books #NowReading #TheStoryGraph'
|
||||
if (url.includes('trakt.tv')) return '#Movies #Watching #Trakt'
|
||||
return tagMap[url] || ''
|
||||
},
|
||||
webmentionsByUrl: (webmentions, url) => {
|
||||
const allowedTypes = ['mention-of', 'in-reply-to', 'like-of', 'repost-of']
|
||||
|
||||
const data = {
|
||||
'like-of': [],
|
||||
'repost-of': [],
|
||||
'in-reply-to': [],
|
||||
'mention-of': [],
|
||||
'link-to': [],
|
||||
}
|
||||
|
||||
const hasRequiredReplyFields = (entry) => {
|
||||
const { author, published, content } = entry
|
||||
return author.name && author.photo && published && content
|
||||
}
|
||||
|
||||
const hasRequiredMentionFields = (entry) => {
|
||||
const { name, url } = entry
|
||||
return name && url
|
||||
}
|
||||
|
||||
const filtered =
|
||||
webmentions
|
||||
.filter((entry) => entry['wm-target'] === `${BASE_URL}${url}`)
|
||||
.filter((entry) => allowedTypes.includes(entry['wm-property'])) || []
|
||||
|
||||
filtered.forEach((m) => {
|
||||
if (data[m['wm-property']]) {
|
||||
const isReply = m['wm-property'] === 'in-reply-to'
|
||||
const isMention = m['wm-property'] === 'mention-of'
|
||||
const isValidReply = (isReply || isMention) && hasRequiredReplyFields(m)
|
||||
if (isReply || isMention) {
|
||||
if (isValidReply) {
|
||||
m.sanitized = sanitizeHTML(m.content.html)
|
||||
data[m['wm-property']].unshift(m)
|
||||
}
|
||||
|
||||
if (isMention && hasRequiredMentionFields(m)) data['link-to'].push(m)
|
||||
return
|
||||
}
|
||||
data[m['wm-property']].unshift(m)
|
||||
}
|
||||
})
|
||||
|
||||
data['in-reply-to'] = [...data['in-reply-to'], ...data['mention-of']]
|
||||
data['in-reply-to'].sort((a, b) =>
|
||||
a.published > b.published ? 1 : b.published > a.published ? -1 : 0
|
||||
)
|
||||
|
||||
return data
|
||||
},
|
||||
}
|
210
config/filters/index.js
Normal file
210
config/filters/index.js
Normal file
|
@ -0,0 +1,210 @@
|
|||
const { DateTime } = require('luxon')
|
||||
const markdownIt = require('markdown-it')
|
||||
const { URL } = require('url')
|
||||
const marked = require('marked')
|
||||
const sanitizeHTML = require('sanitize-html')
|
||||
|
||||
const utmPattern = /[?&](utm_[^&=]+=[^&#]*)/gi
|
||||
const BASE_URL = 'https://coryd.dev'
|
||||
|
||||
module.exports = {
|
||||
// general
|
||||
trim: (string, limit) => {
|
||||
return string.length <= limit ? string : `${string.slice(0, limit)}...`
|
||||
},
|
||||
stripIndex: (path) => {
|
||||
return path.replace('/index.html', '/')
|
||||
},
|
||||
mdToHtml: (content) => {
|
||||
return marked.parse(content)
|
||||
},
|
||||
btoa: (string) => {
|
||||
return btoa(string)
|
||||
},
|
||||
dashLower: (string) => string.replace(/\s+/g, '-').toLowerCase(),
|
||||
encodeAmp: (string) => {
|
||||
if (!string) return
|
||||
const pattern = /&(?!(?:[a-zA-Z]+|#[0-9]+|#x[0-9a-fA-F]+);)/g
|
||||
const replacement = '&'
|
||||
return string.replace(pattern, replacement)
|
||||
},
|
||||
stripUtm: (string) => {
|
||||
if (!string) return
|
||||
return string.replace(utmPattern, '')
|
||||
},
|
||||
getPostImage: (image) => {
|
||||
if (image && image !== '') return image
|
||||
return `${BASE_URL}/assets/img/social-card.jpg`
|
||||
},
|
||||
getPopularPosts: (posts, analytics) => {
|
||||
return posts
|
||||
.filter((post) => {
|
||||
if (analytics.find((p) => p.page === post.url)) return true
|
||||
})
|
||||
.sort((a, b) => {
|
||||
const visitors = (page) => analytics.filter((p) => p.page === page.url).pop().visitors
|
||||
return visitors(b) - visitors(a)
|
||||
})
|
||||
},
|
||||
tagLookup: (url, tagMap) => {
|
||||
if (!url) return
|
||||
if (url.includes('thestorygraph.com')) return '#Books #NowReading #TheStoryGraph'
|
||||
if (url.includes('trakt.tv')) return '#Movies #Watching #Trakt'
|
||||
return tagMap[url] || ''
|
||||
},
|
||||
webmentionsByUrl: (webmentions, url) => {
|
||||
const allowedTypes = ['mention-of', 'in-reply-to', 'like-of', 'repost-of']
|
||||
|
||||
const data = {
|
||||
'like-of': [],
|
||||
'repost-of': [],
|
||||
'in-reply-to': [],
|
||||
'mention-of': [],
|
||||
'link-to': [],
|
||||
}
|
||||
|
||||
const hasRequiredReplyFields = (entry) => {
|
||||
const { author, published, content } = entry
|
||||
return author.name && author.photo && published && content
|
||||
}
|
||||
|
||||
const hasRequiredMentionFields = (entry) => {
|
||||
const { name, url } = entry
|
||||
return name && url
|
||||
}
|
||||
|
||||
const filtered =
|
||||
webmentions
|
||||
.filter((entry) => entry['wm-target'] === `${BASE_URL}${url}`)
|
||||
.filter((entry) => allowedTypes.includes(entry['wm-property'])) || []
|
||||
|
||||
filtered.forEach((m) => {
|
||||
if (data[m['wm-property']]) {
|
||||
const isReply = m['wm-property'] === 'in-reply-to'
|
||||
const isMention = m['wm-property'] === 'mention-of'
|
||||
const isValidReply = (isReply || isMention) && hasRequiredReplyFields(m)
|
||||
if (isReply || isMention) {
|
||||
if (isValidReply) {
|
||||
m.sanitized = sanitizeHTML(m.content.html)
|
||||
data[m['wm-property']].unshift(m)
|
||||
}
|
||||
|
||||
if (isMention && hasRequiredMentionFields(m)) data['link-to'].push(m)
|
||||
return
|
||||
}
|
||||
data[m['wm-property']].unshift(m)
|
||||
}
|
||||
})
|
||||
|
||||
data['in-reply-to'] = [...data['in-reply-to'], ...data['mention-of']]
|
||||
data['in-reply-to'].sort((a, b) =>
|
||||
a.published > b.published ? 1 : b.published > a.published ? -1 : 0
|
||||
)
|
||||
|
||||
return data
|
||||
},
|
||||
|
||||
// dates
|
||||
readableDate: (date) => {
|
||||
return DateTime.fromISO(date).toFormat('LLLL d, yyyy')
|
||||
},
|
||||
toDateTime: (date) => {
|
||||
const formatted = DateTime.fromISO(date)
|
||||
|
||||
const trail = (number) => {
|
||||
return parseInt(number, 10) < 10 ? `0${number}` : number
|
||||
}
|
||||
|
||||
return `${formatted.year}-${trail(formatted.month)}-${trail(formatted.day)} ${trail(
|
||||
formatted.hour
|
||||
)}:${trail(formatted.minute)}`
|
||||
},
|
||||
toDateTimeFromUnix: (date) => {
|
||||
const formatted = DateTime.fromSeconds(parseInt(date, 10))
|
||||
|
||||
const trail = (number) => {
|
||||
return parseInt(number, 10) < 10 ? `0${number}` : number
|
||||
}
|
||||
|
||||
return `${trail(formatted.month)}.${trail(formatted.day)}.${formatted.year} ${trail(
|
||||
formatted.hour
|
||||
)}:${trail(formatted.minute)}`
|
||||
},
|
||||
isoDateOnly: (date) => {
|
||||
let d = new Date(date)
|
||||
let month = '' + (d.getMonth() + 1)
|
||||
let day = '' + d.getDate()
|
||||
let year = d.getFullYear()
|
||||
|
||||
if (month.length < 2) month = '0' + month
|
||||
if (day.length < 2) day = '0' + day
|
||||
|
||||
return [month, day, year].join('.')
|
||||
},
|
||||
stringToDate: (string) => {
|
||||
if (!string) return
|
||||
return new Date(string)
|
||||
},
|
||||
|
||||
// feeds
|
||||
normalizeEntries: (entries) => {
|
||||
const md = markdownIt({ html: true, linkify: true })
|
||||
const posts = []
|
||||
entries.forEach((entry) => {
|
||||
const dateKey = Object.keys(entry).find((key) => key.includes('date'))
|
||||
const date = new Date(entry[dateKey])
|
||||
let excerpt = ''
|
||||
|
||||
// set the entry excerpt
|
||||
if (entry.description) excerpt = entry.description
|
||||
if (entry.data?.post_excerpt) excerpt = md.render(entry.data.post_excerpt)
|
||||
|
||||
// if there's a valid entry return a normalized object
|
||||
if (entry)
|
||||
posts.push({
|
||||
title: entry.data?.title || entry.title,
|
||||
url: entry.url.includes('http') ? entry.url : new URL(entry.url, BASE_URL).toString(),
|
||||
content: entry.description,
|
||||
date,
|
||||
excerpt,
|
||||
})
|
||||
})
|
||||
return posts
|
||||
},
|
||||
|
||||
// media
|
||||
normalizeMedia: (media) =>
|
||||
media.map((item) => {
|
||||
let normalized = {
|
||||
image: item['image'],
|
||||
url: item['url'],
|
||||
}
|
||||
if (item.type === 'album') {
|
||||
normalized['title'] = item['title']
|
||||
normalized['alt'] = `${item['title']} by ${item['artist']}`
|
||||
normalized['subtext'] = `${item['artist']}`
|
||||
}
|
||||
if (item.type === 'artist') {
|
||||
normalized['title'] = item['title']
|
||||
normalized['alt'] = `${item['plays']} plays of ${item['title']}`
|
||||
normalized['subtext'] = `${item['plays']} plays`
|
||||
}
|
||||
if (item.type === 'movie') normalized['alt'] = item['title']
|
||||
if (item.type === 'book') {
|
||||
normalized['alt'] = `${item['title']} by ${item['author']}`
|
||||
normalized['subtext'] = `${item['percentage']} finished`
|
||||
normalized['percentage'] = item['percentage']
|
||||
}
|
||||
if (item.type === 'tv') {
|
||||
normalized['title'] = item['title']
|
||||
normalized['alt'] = `${item['title']} from ${item['name']}`
|
||||
normalized['subtext'] = item['subtext']
|
||||
}
|
||||
if (item.type === 'tv-range') {
|
||||
normalized['title'] = item['name']
|
||||
normalized['alt'] = `${item['subtext']} from ${item['name']}`
|
||||
normalized['subtext'] = item['subtext']
|
||||
}
|
||||
return normalized
|
||||
}),
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
module.exports = {
|
||||
normalizeMedia: (media) =>
|
||||
media.map((item) => {
|
||||
let normalized = {
|
||||
image: item['image'],
|
||||
url: item['url'],
|
||||
}
|
||||
if (item.type === 'album') {
|
||||
normalized['title'] = item['title']
|
||||
normalized['alt'] = `${item['title']} by ${item['artist']}`
|
||||
normalized['subtext'] = `${item['artist']}`
|
||||
}
|
||||
if (item.type === 'artist') {
|
||||
normalized['title'] = item['title']
|
||||
normalized['alt'] = `${item['plays']} plays of ${item['title']}`
|
||||
normalized['subtext'] = `${item['plays']} plays`
|
||||
}
|
||||
if (item.type === 'movie') normalized['alt'] = item['title']
|
||||
if (item.type === 'book') {
|
||||
normalized['alt'] = `${item['title']} by ${item['author']}`
|
||||
normalized['subtext'] = `${item['percentage']} finished`
|
||||
normalized['percentage'] = item['percentage']
|
||||
}
|
||||
if (item.type === 'tv') {
|
||||
normalized['title'] = item['title']
|
||||
normalized['alt'] = `${item['title']} from ${item['name']}`
|
||||
normalized['subtext'] = item['subtext']
|
||||
}
|
||||
if (item.type === 'tv-range') {
|
||||
normalized['title'] = item['name']
|
||||
normalized['alt'] = `${item['subtext']} from ${item['name']}`
|
||||
normalized['subtext'] = item['subtext']
|
||||
}
|
||||
return normalized
|
||||
}),
|
||||
}
|
70
config/shortcodes/img/index.js
Normal file
70
config/shortcodes/img/index.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
const outdent = require('outdent')
|
||||
const Image = require('@11ty/eleventy-img')
|
||||
|
||||
const img = async (
|
||||
src,
|
||||
alt,
|
||||
className = undefined,
|
||||
loading = 'lazy',
|
||||
widths = [75, 150, 300, 600, 900, 1200],
|
||||
formats = ['webp', 'jpeg'],
|
||||
sizes = '100vw'
|
||||
) => {
|
||||
const imageMetadata = await Image(src, {
|
||||
widths: [...widths, null],
|
||||
formats: [...formats, null],
|
||||
outputDir: './_site/assets/img/cache/',
|
||||
urlPath: '/assets/img/cache/',
|
||||
})
|
||||
|
||||
const stringifyAttributes = (attributeMap) => {
|
||||
return Object.entries(attributeMap)
|
||||
.map(([attribute, value]) => {
|
||||
if (typeof value === 'undefined') return ''
|
||||
return `${attribute}="${value}"`
|
||||
})
|
||||
.join(' ')
|
||||
}
|
||||
|
||||
const sourceHtmlString = Object.values(imageMetadata)
|
||||
.map((images) => {
|
||||
const { sourceType } = images[0]
|
||||
const sourceAttributes = stringifyAttributes({
|
||||
type: sourceType,
|
||||
srcset: images.map((image) => image.srcset).join(', '),
|
||||
sizes,
|
||||
})
|
||||
|
||||
return `<source ${sourceAttributes}>`
|
||||
})
|
||||
.join('\n')
|
||||
|
||||
const getLargestImage = (format) => {
|
||||
const images = imageMetadata[format]
|
||||
return images[images.length - 1]
|
||||
}
|
||||
|
||||
const largestUnoptimizedImg = getLargestImage(formats[0])
|
||||
const imgAttributes = stringifyAttributes({
|
||||
src: largestUnoptimizedImg.url,
|
||||
width: largestUnoptimizedImg.width,
|
||||
height: largestUnoptimizedImg.height,
|
||||
alt,
|
||||
loading,
|
||||
decoding: 'async',
|
||||
})
|
||||
|
||||
const imgHtmlString = `<img ${imgAttributes}>`
|
||||
const pictureAttributes = stringifyAttributes({
|
||||
class: className,
|
||||
})
|
||||
|
||||
const picture = `<picture ${pictureAttributes}>
|
||||
${sourceHtmlString}
|
||||
${imgHtmlString}
|
||||
</picture>`
|
||||
|
||||
return outdent`${picture}`
|
||||
}
|
||||
|
||||
module.exports = img
|
4
config/shortcodes/index.js
Normal file
4
config/shortcodes/index.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
const img = require('./img')
|
||||
module.exports = {
|
||||
img,
|
||||
}
|
Reference in a new issue