]> Witch of Git - web/blog/blob - .eleventy.js
Add favicon
[web/blog] / .eleventy.js
1 const pluginRss = require("@11ty/eleventy-plugin-rss");
2 const pluginSyntaxHighlight = require("@11ty/eleventy-plugin-syntaxhighlight");
3 const Nunjucks = require("nunjucks");
4 const dateFilter = require("nunjucks-date-filter");
5 const md = require("markdown-it")();
6 const CleanCSS = require("clean-css");
7 const htmlMinifier = require("html-minifier");
8 const util = require("util");
9
10 module.exports = (eleventyConfig) => {
11 eleventyConfig.addNunjucksFilter('date', dateFilter);
12 eleventyConfig.addPlugin(pluginRss);
13 eleventyConfig.addPlugin(pluginSyntaxHighlight);
14
15 eleventyConfig.addTransform("html-minifier", htmlMinifierTransform);
16
17 eleventyConfig.addPassthroughCopy("img");
18 eleventyConfig.addPassthroughCopy("static");
19 eleventyConfig.addPassthroughCopy("stamps");
20 eleventyConfig.addPassthroughCopy({ "favicon": "/" });
21
22 eleventyConfig.addNunjucksShortcode("youtube", youtubeShortcode);
23 eleventyConfig.addPairedNunjucksShortcode("tweet", tweetShortcode);
24 eleventyConfig.addPairedShortcode("aside", asideShortcode);
25 eleventyConfig.addPairedShortcode("figure", figureShortcode);
26
27 eleventyConfig.addFilter("markdown", value => md.renderInline(value));
28 eleventyConfig.addFilter("groupby", groupbyFilter);
29 eleventyConfig.addFilter("cssmin", css =>
30 new CleanCSS({}).minify(css).styles);
31 eleventyConfig.addFilter("debug", util.inspect);
32
33 eleventyConfig.setDataDeepMerge(true);
34
35 eleventyConfig.addCollection("years", collection => {
36 const posts = collection.getFilteredByTag("posts");
37 const items = groupby(posts, item => item.date.getFullYear());
38 return items.reduce((obj, [k, v]) => (obj[k] = v, obj), {});
39 });
40
41 return {
42 markdownTemplateEngine: "njk",
43 };
44 };
45
46 function access(item, path) {
47 const segments = path.split(".");
48 for (const seg of segments) {
49 if (item === undefined) { return null; }
50 if (seg.endsWith("()")) {
51 const method = item[seg.slice(0, -2)];
52 if (method === undefined) { return null; }
53 item = method.bind(item)();
54 } else {
55 item = item[seg];
56 }
57 }
58 return item;
59 }
60
61 function groupby(items, keyFn) {
62 const results = [];
63 for (const item of items) {
64 const key = keyFn(item);
65 if (results.length == 0 || key != results[results.length-1][0]) {
66 results.push([key, [item]]);
67 } else {
68 results[results.length-1][1].push(item);
69 }
70 }
71 return results;
72 }
73
74 function groupbyFilter(items, path) {
75 return groupby(items, item => access(item, path));
76 }
77
78 function youtubeShortcode(items, inWidth = 560, inHeight = 315) {
79 const width = items.width || inWidth;
80 const height = items.height || inHeight;
81 const allow = items.allow || "accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
82 const border = items.border || "0";
83 const video = items.video || items;
84 if (!video) {
85 throw "Required argument 'video'.";
86 }
87 const src = "https://www.youtube.com/embed/" + video;
88 return `<div class="youtube row hcenter">
89 <iframe width="${width}" height="${height}" src="${src}"
90 frameborder="${border}" allow="${allow}" allowfullscreen></iframe>
91 </div>`;
92 }
93
94 function tweetShortcode(content, items) {
95 // @TODO: Handle parsing date
96 return `<div class="row hcenter">
97 <blockquote class="twitter-tweet">
98 <p lang="en" dir="ltr">${content}</p> &mdash; ${items.name} (@${items.at})
99 <a href="${items.link}">${items.date}</a>
100 </blockquote>
101 <script async src="https://platform.twitter.com/widgets.js" charset="utf-8">
102 </script>
103 </div>`;
104 }
105
106 function asideShortcode(content, style='') {
107 const html = md.render(content);
108 if (style) {
109 return `<aside class="${style}">${html}</aside>`;
110 } else {
111 return `<aside>${html}</aside>`;
112 }
113 }
114
115 function figureShortcode(content, { src, alt }) {
116 const captionHtml = md.render(content);
117 return `<figure class="col hcenter">
118 <img src="${src}" alt="${alt}">
119 <figcaption>${captionHtml}</figcaption>
120 </figure>`;
121 }
122
123 function htmlMinifierTransform(content, outputPath) {
124 if (outputPath.endsWith(".html")) {
125 return htmlMinifier.minify(content, {
126 useShortDoctype: true,
127 removeComments: true,
128 collapseWhitespace: true,
129 });
130 }
131 return content;
132 }