import { DateTime } from "luxon"; import { eleventyImageTransformPlugin } from "@11ty/eleventy-img"; import markdownIt from "markdown-it"; import markdownItFootnote from "markdown-it-footnote"; import markdownItAnchor from "markdown-it-anchor"; import mdfigcaption from 'markdown-it-image-figures'; import pluginRss from "@11ty/eleventy-plugin-rss"; import pluginSyntaxHighlight from "@11ty/eleventy-plugin-syntaxhighlight"; import pluginBundle from "@11ty/eleventy-plugin-bundle"; import pluginNavigation from "@11ty/eleventy-navigation"; import prettier from "prettier"; import { EleventyHtmlBasePlugin } from "@11ty/eleventy"; import {dateSuffixAdder, monthMap, timeFormatter} from "./public/js/modules/mastodonDateTools.js"; const figoptions = { figcaption: true }; export default async function(eleventyConfig) { // Helper Functions const multiReplace = (text, replacementTable) => { let newText = text; replacementTable.forEach(x => { newText = newText.replace(x[0], x[1]) }); return newText; }; // Transforms eleventyConfig.addTransform("prettier", function (content, outputPath) { if (outputPath && outputPath.endsWith(".html")) { return prettier.format(content, {parser: "html", bracketSameLine: true, vueIndentScriptAndStyle: true, singleAttributePerLine: true, htmlWhitespaceSensitivity: "ignore"}); } else { return content; } }); eleventyConfig.addWatchTarget("content/**/*.{svg,webp,png,jpeg}"); // Official plugins /* eleventyConfig.addPlugin(eleventyImageTransformPlugin, { extensions: "html", formats: ["webp"], widths: [270,540,810,1080], defaultAttributes: { loading: "lazy", decoding: "async", }, urlPath: "/img/", });*/ eleventyConfig.addPlugin(pluginRss); eleventyConfig.addPlugin(pluginSyntaxHighlight, { preAttributes: { tabindex: 0 } }); eleventyConfig.addPlugin(pluginNavigation); eleventyConfig.addPlugin(EleventyHtmlBasePlugin); eleventyConfig.addPlugin(pluginBundle); // Filters eleventyConfig.addFilter("readableDate", (dateObj, format, zone) => { // Formatting tokens for Luxon: https://moment.github.io/luxon/#/formatting?id=table-of-tokens return DateTime.fromJSDate(dateObj, { zone: zone || "utc" }).toFormat(format || "dd LLLL yyyy"); }); eleventyConfig.addFilter('htmlDateString', (dateObj) => { // dateObj input: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-date-string return DateTime.fromJSDate(dateObj, { zone: 'utc' }).toFormat('yyyy-LL-dd'); }); eleventyConfig.addFilter("removeMostRecent", arr => { return arr.slice(0, arr.length-1); }); // Shortcodes // Cowsay eleventyConfig.addNunjucksFilter("cowsay", cowText => { const cowCaptionReplacementTable = [ [` o ^__^ o (oo)\\_______ (__)\\ )\\/\\ ||----w | || ||`, ''], [/\(\s+/g, ''], [/\s+\(/g, ''], [/_{3,}/g, ''], [/-{3,}/g, ''], [/\s\)/g, ''], [/\n/g, ''], [/\s{2,}/g, ' '], [/^ /, ''] ]; return `
A cow thinking: ${multiReplace(cowText, cowCaptionReplacementTable)}. The cow is illustrated using preformatted text characters.
`; }); // Embed a toot eleventyConfig.addAsyncShortcode("toot", async function(instance, ID) { const tootData = await fetch( `https://${instance}/api/v1/statuses/${ID}` ); const toot = await tootData.json(); const dateObj = new Date(toot.created_at); const dateTime = `${dateObj.getDate()}${dateSuffixAdder(dateObj.getDate())} of ${monthMap[dateObj.getMonth()]}, ${dateObj.getFullYear()}, at ${timeFormatter(dateObj.getHours(), dateObj.getMinutes())}`; return ` ` }); // Passthrough eleventyConfig.addPassthroughCopy({ 'public/xsl/*': "/xsl/" }); eleventyConfig.addPassthroughCopy({ 'public/img/*': "/img/" }); eleventyConfig.addPassthroughCopy({ 'public/robots.txt': "/" }); eleventyConfig.addPassthroughCopy({ 'public/js/*': "/js/" }); eleventyConfig.addPassthroughCopy({ 'public/js/webComponents/*': "/js/webComponents" }); eleventyConfig.addPassthroughCopy({ 'public/js/modules/*': "/js/modules" }); // Copying so that basic.xsl can use it eleventyConfig.addPassthroughCopy({ 'public/css/index.css': "/css/index.css" }); eleventyConfig.addPassthroughCopy({ 'public/css/webfonts/*': "/css/webfonts/" }); // Get the first `n` elements of a collection. eleventyConfig.addFilter("head", (array, n) => { if (!Array.isArray(array) || array.length === 0) { return []; } if (n < 0) { return array.slice(n); } return array.slice(0, n); }); // Return the smallest number argument eleventyConfig.addFilter("min", (...numbers) => { return Math.min.apply(null, numbers); }); // Return all the tags used in a collection eleventyConfig.addFilter("getAllTags", collection => { let tagSet = new Set(); for (let item of collection) { (item.data.tags || []).forEach(tag => tagSet.add(tag)); } return Array.from(tagSet); }); eleventyConfig.addFilter("filterTagList", function filterTagList(tags) { return (tags || []).filter(tag => ["all", "nav", "post", "posts"].indexOf(tag) === -1); }); // Customize Markdown library settings: let markdownItOptions = { html: true, typographer: true }; let mdLib = markdownIt(markdownItOptions); eleventyConfig.amendLibrary("md", mdLib => { mdLib .use(markdownItAnchor, { permalink: markdownItAnchor.permalink.ariaHidden({ placement: "after", class: "header-anchor", symbol: "#", ariaHidden: false }), level: [1, 2, 3, 4], slugify: eleventyConfig.getFilter("slugify") }) .use(markdownItFootnote) .use(mdfigcaption, figoptions); }); eleventyConfig.setLibrary("md", mdLib); return { templateFormats: [ "md", "njk", "html", "liquid", ], markdownTemplateEngine: "njk", htmlTemplateEngine: "njk", dir: { input: "content", // default: "." includes: "../_includes", // default: "_includes" data: "../_data", // default: "_data" output: "_site" }, pathPrefix: "/", }; };