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