const syntaxHighlight = require('@11ty/eleventy-plugin-syntaxhighlight'); const pluginRss = require('@11ty/eleventy-plugin-rss'); const timeToRead = require('eleventy-plugin-time-to-read'); const safeLinks = require('@sardine/eleventy-plugin-external-links'); const eleventySass = require("@11tyrocks/eleventy-plugin-sass-lightningcss"); const related = require("eleventy-plugin-related"); const markdownIt = require("markdown-it"); const markdownItAnchor = require("markdown-it-anchor"); module.exports = function (eleventyConfig) { const parseDate = (str) => { if (str instanceof Date) { return str; } return Date.parse(str); }; const formatPart = (part, date) => new Intl.DateTimeFormat("en", part).format(date); eleventyConfig.setNunjucksEnvironmentOptions({ lstripBlocks: true, trimBlocks: true }); eleventyConfig.setLibrary("md", markdownIt({ "html": true }).use(markdownItAnchor, { "level": 2 })); eleventyConfig.addPlugin(pluginRss); eleventyConfig.addPlugin(syntaxHighlight); eleventyConfig.addPlugin(timeToRead); eleventyConfig.addPlugin(safeLinks); eleventyConfig.addPlugin(eleventySass); eleventyConfig.addPassthroughCopy({ "src/static": "/" }); eleventyConfig.addFilter("date_to_datetime", (obj) => { const date = parseDate(obj); return date.toISOString(); }); eleventyConfig.addFilter("date_formatted", (obj) => { const date = parseDate(obj); const month = formatPart({ month: "short" }, date); const day = formatPart({ day: "numeric" }, date); const year = formatPart({ year: "numeric" }, date); const hours = date.getUTCHours(); const minutes = date.getUTCMinutes(); if (hours != 0 && minutes != 0) { return `${month} ${day}, ${year} - ${hours}:${minutes} UTC`; } return `${month} ${day}, ${year}`; }); eleventyConfig.addFilter('urlescape', str => { return str.split('/').map(part => encodeURI(part)).join('/') }); eleventyConfig.addFilter("related", function(obj) { const post = this.ctx; const posts = this.ctx.collections.posts.map(post => post.data); const tagScore = (a, b) => { const total = a.tags.length + b.tags.length; const intersection = a.tags.filter(tag => b.tags.includes(tag)).length; return (intersection * 2) / total; } const results = related.related({ serializer: (doc) => [doc.title, doc.description], weights: [10, 10], })(post, posts).map(result => { return { relative: result.relative + tagScore(post, result.document), document: result.document } }); return results.filter(result => result.relative > 0.2).sort((a, b) => a.relative - b.relative).reverse().slice(0,3); }); eleventyConfig.addCollection('posts', collection => { return collection.getFilteredByGlob('src/posts/*.md').reverse() }); return { templateFormats: ["njk", "md", "html"], dir: { input: "src", includes: "_includes", data: "_data", output: "www", }, markdownTemplateEngine: "njk", htmlTemplateEngine: "njk", dataTemplateEngine: "njk", passthroughFileCopy: false, }; };