2021-11-17 15:00:34 -07:00
const { DateTime } = require ( 'luxon' )
2023-03-27 12:20:01 -06:00
const fs = require ( 'fs' ) . promises
2023-10-18 01:36:58 -06:00
const path = require ( 'path' )
2021-11-17 15:00:34 -07:00
const pluginRss = require ( '@11ty/eleventy-plugin-rss' )
const pluginSyntaxHighlight = require ( '@11ty/eleventy-plugin-syntaxhighlight' )
const pluginNavigation = require ( '@11ty/eleventy-navigation' )
const markdownIt = require ( 'markdown-it' )
2023-11-01 10:32:36 -06:00
const markdownItAnchor = require ( 'markdown-it-anchor' )
2023-03-27 12:20:01 -06:00
const createHash = require ( 'crypto' ) . createHash
2023-10-18 01:36:58 -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
2023-02-06 19:20:35 -07:00
const dirs = {
2023-11-01 10:32:36 -06:00
input : '_src' ,
includes : '_includes' ,
data : '_data' ,
output : '_site' ,
2023-02-06 19:20:35 -07:00
}
2023-03-02 11:59:59 -07:00
module . exports = ( eleventyConfig ) => {
2023-03-04 12:06:37 -07:00
2023-11-01 10:32:36 -06:00
eleventyConfig . setServerOptions ( {
liveReload : false ,
} )
// Add plugins
eleventyConfig . addPlugin ( pluginRss )
eleventyConfig . addPlugin ( pluginSyntaxHighlight )
eleventyConfig . addPlugin ( pluginNavigation )
// https://www.11ty.dev/docs/data-deep-merge/
eleventyConfig . setDataDeepMerge ( true )
// Alias `layout: post` to `layout: layouts/post.njk`
eleventyConfig . addLayoutAlias ( 'post' , 'layouts/post.njk' )
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 )
)
// Sanitize out apostrophes
eleventyConfig . addFilter ( 'noApostrophes' , ( str ) =>
str . replace ( /['"]+/g , '' )
)
// Return the smallest number argument
eleventyConfig . addFilter ( 'min' , ( ... numbers ) =>
Math . min . apply ( null , numbers )
)
eleventyConfig . addFilter ( 'toFixed' , ( num , digits ) =>
num ? num . toFixed ( digits ) : ''
)
eleventyConfig . addFilter ( 'srintegrity' , async ( asset , bits = 256 ) =>
` sha ${ String ( bits ) } - ` +
createHash ( ` sha ${ String ( bits ) } ` )
. update ( await fs . readFile ( ` ${ dirs . input } ${ asset } ` ) )
. digest ( 'base64' )
)
eleventyConfig . addFilter ( 'filterCatList' , cats =>
// should match the list in categories.njk
( cats || [ ] ) . filter ( cat => [ 'all' , 'nav' , 'post' , 'posts' ] . indexOf ( cat ) === - 1 )
)
eleventyConfig . addFilter ( 'filterTagList' , tags =>
// should match the list in tags.njk
( tags || [ ] ) . filter ( tag => [ 'all' , 'nav' , 'post' , 'posts' ] . indexOf ( tag ) === - 1 )
)
eleventyConfig . addFilter ( 'dimsToVol' , ( dims ) => { return {
in3 : Object . values ( dims . in ) . reduce ( ( a , c ) => a * c , 1 )
} } )
// 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 ] ;
} )
// Markdown "md" filter for nunjucks
// https://github.com/11ty/eleventy/issues/658#issuecomment-599173643
const mdFilter = new markdownIt ( { html : true } )
eleventyConfig . addPairedShortcode ( 'md' , ( content ) =>
mdFilter . render ( content ) )
// Override Browsersync defaults (used only with --serve)
eleventyConfig . setBrowserSyncConfig ( {
callbacks : {
ready : function ( err , browserSync ) {
const content _404 = fs . readFileSync ( '_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 ,
} )
eleventyConfig . addPassthroughCopy ( '_src/assets/fonts' )
eleventyConfig . addPassthroughCopy ( '_src/assets/base.css' )
eleventyConfig . addPassthroughCopy ( '_src/assets/shop.css' )
eleventyConfig . addPassthroughCopy ( '_src/assets/site.webmanifest' )
eleventyConfig . addPassthroughCopy ( '_src/assets/scripts' )
// 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 " > < / p i c t u r e > < / 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> `
)
// 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 ,
} ) )
// Products and categories collections
eleventyConfig . addCollection ( 'products' , async ( ca ) =>
ca . getFilteredByTag ( 'product' )
)
eleventyConfig . addCollection ( 'featured' , async ( ca ) =>
ca . getFilteredByTags ( 'product' , 'featured' )
)
eleventyConfig . addCollection ( 'computers' , async ( ca ) =>
ca . getFilteredByTags ( 'product' , 'computer' )
)
eleventyConfig . addCollection ( 'desktops' , async ( ca ) =>
ca . getFilteredByTags ( 'product' , 'computer' , 'desktop' )
)
eleventyConfig . addCollection ( 'laptops' , async ( ca ) =>
ca . getFilteredByTags ( 'product' , 'computer' , 'laptop' )
)
eleventyConfig . addCollection ( 'all-in-ones' , async ( ca ) =>
ca . getFilteredByTags ( 'product' , 'computer' , 'all-in-one' )
)
eleventyConfig . addCollection ( 'phones' , async ( ca ) =>
ca . getFilteredByTags ( 'product' , 'phone' )
)
eleventyConfig . addCollection ( 'routers' , async ( ca ) =>
ca . getFilteredByTags ( 'product' , 'router' )
)
eleventyConfig . addCollection ( 'accessories' , async ( ca ) =>
ca . getFilteredByTags ( 'product' , 'accessory' )
)
return {
// Control which files Eleventy will process
// e.g.: *.md, *.njk, *.html, *.liquid
templateFormats : [
'md' ,
'txt' ,
'njk' ,
'html' ,
'liquid' ,
'pdf' ,
'png' ,
'webp' ,
'jpg' ,
'svg' ,
'ico' ,
'gif' ,
'mp4' ,
] ,
// -----------------------------------------------------------------
// 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 ,
// Set at top
dir : dirs ,
}
2021-04-16 14:44:02 -06:00
}