devon.lol/.eleventy.js
2024-06-24 00:22:24 -04:00

151 lines
5.4 KiB
JavaScript

const path = require("path");
const markdownIt = require("markdown-it");
const slugify = require("@sindresorhus/slugify");
const markdownItAnchor = require("markdown-it-anchor");
const markdownItObsidian = require("markdown-it-obsidian");
const markdownItAttrs = require("markdown-it-attrs");
const markdownItEleventyImg = require("markdown-it-eleventy-img");
const pluginRss = require("@11ty/eleventy-plugin-rss");
const embedYouTube = require("eleventy-plugin-youtube-embed");
const sanitizeHtml = require("sanitize-html");
const syntaxHighlight = require("@11ty/eleventy-plugin-syntaxhighlight");
const metadata = require("./src/_data/metadata.json");
const sanitize = (html) => {
return sanitizeHtml(html, {
allowedTags: ['b', 'i', 'em', 'strong', 'a'],
allowedAttributes: { 'a': ['href'] }
});
};
module.exports = function(eleventyConfig) {
eleventyConfig.addPlugin(embedYouTube);
eleventyConfig.addPlugin(pluginRss);
eleventyConfig.addPlugin(syntaxHighlight);
eleventyConfig.addPassthroughCopy("css");
eleventyConfig.addPassthroughCopy("fonts");
eleventyConfig.addPassthroughCopy("images/**/*.{gif,png,jpg,jpeg}");
eleventyConfig.addPassthroughCopy({ "favicon": "/" });
eleventyConfig.addPassthroughCopy({
"node_modules/simpledotcss/simple.css": "css/simple.css",
});
eleventyConfig.addPassthroughCopy({ "src/robots.txt": "robots.txt" });
eleventyConfig.addFilter("buildPageTitle", function(title) {
if (this.page.url === '/') {
return title;
} else {
return title + ' ⇢ Devon.LoL 😆';
}
});
eleventyConfig.addFilter("stringToDate", function(value) {
return new Date(value);
});
eleventyConfig.addFilter("formatDatetimeForHumans", function(value) {
const dt = new Date(value);
const formattedDt = new Intl.DateTimeFormat("en", {
dateStyle: "medium",
timeStyle: "medium",
}).format(dt);
return formattedDt;
});
eleventyConfig.addFilter("formatDateForHumans", function(value) {
const dt = new Date(value);
const formattedDt = new Intl.DateTimeFormat("en", {
dateStyle: "medium",
}).format(dt);
return formattedDt;
});
eleventyConfig.addFilter("formatDateForRobots", function(value) {
const dt = new Date(value);
return dt.toISOString();
});
eleventyConfig.addFilter("convertYouTubeURLsToEmbeds", function(value) {
const youtubeUrlRegex = /<p>\s*(?:https?:\/\/)?(?:www\.)?(?:youtube\.com|youtu\.be)\/(?!channel\/|@)([^\s&<>"']*)\s*<\/p>/gim;
return value.replace(youtubeUrlRegex, function(match, videoId) {
return '<iframe width="560" height="315" src="https://www.youtube.com/embed/' + videoId + '" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>';
});
});
eleventyConfig.addFilter('webmentionsByUrl', function(webmentions, url) {
const allowedTypes = ['in-reply-to', 'like-of', 'repost-of'];
const hasRequiredFields = mention => {
const { author, published, content } = mention;
return author.name && published && content;
};
const matchesUrl = mention => {
return mention['wm-target'] === url;
};
const filteredMentions = webmentions
.filter(mention => {
const isAllowedType = allowedTypes.includes(mention['wm-property']);
if (isAllowedType) {
const isReply = mention['wm-property'] === 'in-reply-to';
if (isReply) {
return matchesUrl(mention) && hasRequiredFields(mention);
}
return matchesUrl(mention);
}
}
);
const sanitizedMentions = filteredMentions.map((mention) => {
if (mention?.content?.html) {
mention.content.html = sanitize(mention.content.html);
const mastodonInstance = metadata.author.mastodon.instance;
const mastodonUsername = metadata.author.mastodon.username;
const mentionLink = `<a href="https://${mastodonInstance}/@${mastodonUsername}">@${metadata.author.mastodon.username}</a> `;
if (mention.content.html.startsWith(mentionLink)) {
mention.content.html = mention.content.html.substring(mentionLink.length)
}
}
return mention;
});
const sortedMentions = sanitizedMentions.reduce((accumulator, mention) => {
const key = mention['wm-property'];
const curGroup = accumulator[key] ?? [];
return { ...accumulator, [key]: [...curGroup, mention] };
}, {});
return sortedMentions;
});
eleventyConfig.addTransform('includePrismTheme', function(content, outputPath) {
// Automatically inject the Prism theme CSS, but only in HTML files that need it.
if (outputPath.endsWith('.html') && content.includes('<pre class="language-')) {
return content.replace(
'</head>',
'<link rel="stylesheet" href="/css/prism-synthwave84.css"></head>'
);
}
return content;
});
const markdownLibrary = markdownIt({ html: true })
.use(markdownItAnchor, { slugify })
.use(
markdownItObsidian({
slugifyOnPageLinks: slugify,
})
)
.use(markdownItAttrs)
.use(markdownItEleventyImg, {
imgOptions: {
widths: [75, 150, 300, 600, 900, 1100],
outputDir: path.join("dist", "img"),
},
globalAttributes: {
loading: "lazy",
decoding: "async",
sizes: "100vw",
},
});
eleventyConfig.setLibrary("md", markdownLibrary);
return {
dir: {
input: "src",
output: "dist",
},
};
};