2021-06-17 17:02:30 -06:00
const { DateTime } = require ( 'luxon' )
2023-10-18 01:02:56 -06:00
const fs = require ( 'fs' ) . promises
const path = require ( 'path' )
2021-06-17 17:02:30 -06:00
const markdownIt = require ( 'markdown-it' )
const markdownItAnchor = require ( 'markdown-it-anchor' )
2023-10-17 23:35:54 -06:00
const pluginImage = require ( '@11ty/eleventy-img' )
// Widths in pixels of responsive images to be generated
const IMAGE _SIZES = [ 300 , 600 , 900 , 1200 ]
2018-01-16 20:08:47 -07:00
2018-01-22 07:17:48 -07:00
module . exports = function ( eleventyConfig ) {
2019-11-11 15:22:08 -07:00
2023-11-01 10:30:43 -06:00
// 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 ) } ` ,
} )
2023-10-17 23:35:54 -06:00
const lowsrc = metadata . webp [ 0 ]
const highsrc = metadata . webp [ metadata . webp . length - 1 ]
2023-11-01 10:30:43 -06:00
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 " > < / p i c t u r e > < / a > `
2023-10-17 23:35:54 -06:00
} )
2023-11-01 10:30:43 -06:00
// 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 ( {
2023-10-30 21:47:59 -06:00
html : true ,
breaks : true ,
linkify : true ,
} ) . use ( markdownItAnchor , {
permalink : markdownItAnchor . permalink . headerLink ( ) ,
level : [ 2 , 3 , 4 , 5 , 6 ] ,
slugify : eleventyConfig . getFilter ( 'slugify' ) ,
tabIndex : false ,
} ) )
2018-06-18 08:00:00 -06:00
2023-11-01 10:30:43 -06:00
// 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`.
// Don’ t worry about leading and trailing slashes, we normalize these.
// If you don’ t 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'
}
}
2021-06-17 17:02:30 -06:00
}