www/eleventy.config.js

192 lines
6.3 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

const { DateTime } = require('luxon')
const fs = require('fs').promises
const path = require('path')
const markdownIt = require('markdown-it')
const markdownItAnchor = require('markdown-it-anchor')
const pluginImage = require('@11ty/eleventy-img')
// Widths in pixels of responsive images to be generated
const IMAGE_SIZES = [300, 600, 900, 1200]
module.exports = function(eleventyConfig) {
// https://www.11ty.dev/docs/data-deep-merge/
eleventyConfig.setDataDeepMerge(true)
// Optimized images
// https://www.11ty.dev/docs/plugins/image/#make-your-own-markup
eleventyConfig.addShortcode('image', async (src, alt) => {
const metadata = await pluginImage(`./_src${src}`, {
widths: [...IMAGE_SIZES, 'auto'],
formats: ['auto', 'webp', 'avif'],
// https://www.11ty.dev/docs/plugins/image/#custom-filenames
filenameFormat: (id, src, width, format) =>
`${path.basename(src,path.extname(src))}-${width}w.${format}`,
// https://alexpeterhall.com/blog/2021/04/05/responsive-images-eleventy/#eleventy-configuration
urlPath: path.dirname(src),
outputDir: `_site/${path.dirname(src)}`,
})
const lowsrc = metadata.webp[0]
const highsrc = metadata.webp[metadata.webp.length - 1]
return `<a href="${src}"><picture>${Object.values(metadata).map(imageFormat =>
`\t<source type="${imageFormat[0].sourceType}" srcset="${imageFormat.map(entry => entry.srcset).join(', ')}" sizes="${IMAGE_SIZES.reverse().reduce((str,size) =>
`(max-width:${size}px) ${size}px, ${str}`,'100vw')}">`).join('')}<img src="${lowsrc.url}" width="${highsrc.width}" height="${highsrc.height}" alt="${alt}" decoding="async"></picture></a>`
})
// Video embed
eleventyConfig.addShortcode('vid', (src, autoplay=false) =>
`<video controls ${(autoplay)?'autoplay':''}width="100%"><source src="${src}" type="video/${src.split('.').pop()}">Embedded videos are not supported in this browser.</video>`
)
eleventyConfig.addShortcode('vidraw', (src) =>
`<video width="100%"><source src="${src}">Embedded videos are not supported in this browser.</video>`
)
// YouTube
eleventyConfig.addShortcode('yt', (shortcode) =>
`<iframe width="100%" height="500vh" src="https://www.youtube.com/embed/${shortcode}" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>`
)
// Audio embed
eleventyConfig.addShortcode('audio', (src, fmt) =>
`<audio controls><source src="${src}" type="audio/${fmt}">Embedded audio is not supported in this browser.</audio>`
)
// iFrame
eleventyConfig.addShortcode('iframe', (url, height) =>
`<iframe width="100%" height="${height}" src="${url}"</iframe>`
)
eleventyConfig.addFilter('readableDate', dateObj =>
DateTime.fromJSDate(dateObj, {zone: 'utc'}).toFormat('dd LLL yyyy')
)
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-date-string
eleventyConfig.addFilter('htmlDateString', (dateObj) =>
DateTime.fromJSDate(dateObj, {zone: 'utc'}).toFormat('yyyy-LL-dd')
)
// Get the first `n` elements of a collection.
eleventyConfig.addFilter('head', (array, n) =>
(n<0)? array.slice(n): array.slice(0, n)
)
// Return the smallest number argument
eleventyConfig.addFilter('min', (...numbers) =>
Math.min.apply(null, numbers)
)
eleventyConfig.addFilter('filterTagList', tags =>
// should match the list in tags.njk
(tags || []).filter(tag => ['all', 'nav', 'post', 'posts'].indexOf(tag) === -1)
)
// Convert text to hex
eleventyConfig.addFilter('toHex', (str) => {
let hex = ''
for(let i=0; i<str.length; i++){
let h = str.codePointAt(i).toString(16)
if(h.length===1) h='0'+h
hex += h + ' '
if( h.length>4 ) i++
} return hex.trim()
})
// Fold lines
eleventyConfig.addFilter('fold', (str, size) => {
// https://stackoverflow.com/a/29202760/3006854
const numChunks = Math.ceil(str.length/size)
const chunks = new Array(numChunks)
for (let i = 0, o = 0; i < numChunks; ++i, o += size)
chunks[i] = str.substr(o, size)
return chunks.join('\n')
})
// Create an array of all tags
eleventyConfig.addCollection('tagList', function(collection) {
let tagSet = new Set()
collection.getAll().forEach(item => {
(item.data.tags || []).forEach(tag => tagSet.add(tag))
}); return [...tagSet]
})
// Customize Markdown library and settings:
eleventyConfig.setLibrary('md', markdownIt({
html: true,
breaks: true,
linkify: true,
}).use(markdownItAnchor, {
permalink: markdownItAnchor.permalink.headerLink(),
level: [2, 3, 4, 5, 6],
slugify: eleventyConfig.getFilter('slugify'),
tabIndex: false,
}))
// Override Browsersync defaults (used only with --serve)
eleventyConfig.setBrowserSyncConfig({
callbacks: {
ready: async (err, browserSync) => {
const content_404 = await fs.readFile('_site/404.html')
browserSync.addMiddleware('*', (req, res) => {
// Provides the 404 content without redirect.
res.writeHead(404, {
'Content-Type': 'text/html charset=UTF-8' })
res.write(content_404)
res.end()
})
},
},
ui: false,
ghostMode: false
})
return {
templateFormats: [
'md',
'njk',
'html',
'liquid',
'css',
'png',
'webp',
'jpg',
'gif',
'js',
'crt',
'pem',
'ttf',
'webmanifest',
],
// -----------------------------------------------------------------
// If your site deploys to a subdirectory, change `pathPrefix`.
// Dont worry about leading and trailing slashes, we normalize these.
// If you dont have a subdirectory, use "" or "/' (they do the same thing)
// This is only used for link URLs (it does not affect your file structure)
// Best paired with the `url` filter: https://www.11ty.dev/docs/filters/url/
// You can also pass this in on the command line using `--pathprefix`
// Optional (default is shown)
pathPrefix: '/',
// -----------------------------------------------------------------
// Pre-process *.md files with: (default: `liquid`)
markdownTemplateEngine: 'njk',
// Pre-process *.html files with: (default: `liquid`)
htmlTemplateEngine: 'njk',
// Opt-out of pre-processing global data JSON files: (default: `liquid`)
dataTemplateEngine: false,
// These are all optional (defaults are shown):
dir: {
input: '_src',
includes: '_includes',
data: '_data',
output: '_site'
}
}
}