diff --git a/.eleventy.js b/.eleventy.js
index cf74199..a40b966 100644
--- a/.eleventy.js
+++ b/.eleventy.js
@@ -4,6 +4,13 @@ const pluginRss = require("@11ty/eleventy-plugin-rss");
const Image = require("@11ty/eleventy-img");
const htmlmin = require("html-minifier");
const outdent = require("outdent");
+const pluginNavigation = require("@11ty/eleventy-navigation");
+const pluginSyntaxHighlight = require("@11ty/eleventy-plugin-syntaxhighlight");
+const markdownItAnchor = require("markdown-it-anchor");
+const markdownItAttrs = require("markdown-it-attrs");
+const pluginTOC = require("eleventy-plugin-toc");
+const pluginFilters = require("./_config/filters.js");
+const pluginShortCodes = require("./_config/shortcode.js");
/** Maps a config of attribute-value pairs to an HTML string
* representing those same attribute-value pairs.
@@ -83,14 +90,61 @@ const imageShortcode = async (
module.exports = function (eleventyConfig) {
// 11ty plugins
eleventyConfig.addPlugin(pluginRss);
- eleventyConfig.addPlugin(Webmentions, {
- domain: "benkutil.com",
- token: process.env.WEBMENTIONS_TOKEN
+
+ // Only add Webmentions if token is provided
+ if (process.env.WEBMENTIONS_TOKEN) {
+ eleventyConfig.addPlugin(Webmentions, {
+ domain: "benkutil.com",
+ token: process.env.WEBMENTIONS_TOKEN
+ });
+ }
+
+ eleventyConfig.addPlugin(pluginNavigation);
+ eleventyConfig.addPlugin(pluginSyntaxHighlight, {
+ preAttributes: { tabindex: 0 }
+ });
+ eleventyConfig.addPlugin(pluginTOC, {
+ tags: ['h2', 'h3', 'h4', 'h5'],
+ ul: true,
+ flat: false,
+ wrapper: 'div'
});
+ // Add Tufte filters and shortcodes
+ eleventyConfig.addPlugin(pluginFilters);
+ eleventyConfig.addPlugin(pluginShortCodes);
+
// 11ty shortcodes
eleventyConfig.addShortcode('image', imageShortcode);
+ // Configure markdown-it
+ const markdownIt = require("markdown-it");
+ let options = {
+ html: true,
+ breaks: true,
+ linkify: true,
+ typographer: true,
+ };
+ let markdownLib = markdownIt(options).use(markdownItAttrs);
+ eleventyConfig.setLibrary("md", markdownLib);
+
+ 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")
+ });
+ });
+
+ // Pass through Tufte CSS and fonts
+ eleventyConfig.addPassthroughCopy("src/css");
+ eleventyConfig.addPassthroughCopy("src/et-book");
+
// run these configs in production only
if (process.env.ELEVENTY_ENV === 'production') {
eleventyConfig.addTransform("htmlmin", function (content, outputPath) {
diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 0000000..209e3ef
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+20
diff --git a/Readme.md b/Readme.md
index 2de86b9..4ba1202 100644
--- a/Readme.md
+++ b/Readme.md
@@ -4,4 +4,4 @@ Personal website using [11ty](https://11ty.dev) and [Cloudflare Pages](https://p
## Setup
### Environment variables
- `ELEVENTY_ENV` is either `production` or `preview`. Defaults to not set.
-- In Cloudflare Pages, set `NODE_VERSION` to desired nodejs version. Currently set to `16.18` to match GitHub Codespace version.
+- Node version is set to `20` via `.nvmrc` file for compatibility with 11ty and dependencies.
diff --git a/_config/filters.js b/_config/filters.js
new file mode 100644
index 0000000..db6d07a
--- /dev/null
+++ b/_config/filters.js
@@ -0,0 +1,40 @@
+const { DateTime } = require("luxon");
+
+module.exports = function(eleventyConfig) {
+ 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');
+ });
+
+ // 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 the keys used in an object
+ eleventyConfig.addFilter("getKeys", target => {
+ return Object.keys(target);
+ });
+
+ eleventyConfig.addFilter("filterTagList", function filterTagList(tags) {
+ return (tags || []).filter(tag => ["all", "posts"].indexOf(tag) === -1);
+ });
+
+};
diff --git a/_config/shortcode.js b/_config/shortcode.js
new file mode 100644
index 0000000..da1f18f
--- /dev/null
+++ b/_config/shortcode.js
@@ -0,0 +1,23 @@
+module.exports = function(eleventyConfig) {
+ eleventyConfig.addShortcode("notes",(id,content) =>`${content}`);
+
+ eleventyConfig.addShortcode("notesimage",(id,image,alt,content) =>`${content}`);
+
+ eleventyConfig.addShortcode("fullimage",(image,alt) =>`
${content}
`); + + eleventyConfig.addShortcode("epigraphlink",(content,footer,info,url) =>`${content}
${content}
`); +}; diff --git a/package.json b/package.json index 50968b8..34864b4 100644 --- a/package.json +++ b/package.json @@ -22,13 +22,19 @@ "devDependencies": { "@11ty/eleventy": "^2.0.0-beta.3", "@11ty/eleventy-img": "^3.0.0", + "@11ty/eleventy-navigation": "^0.3.5", "@11ty/eleventy-plugin-rss": "^1.2.0", + "@11ty/eleventy-plugin-syntaxhighlight": "^5.0.0", "eleventy-plugin-webmentions": "^2.0.0", "html-minifier": "^4.0.0", + "luxon": "^3.5.0", + "markdown-it-anchor": "^9.2.0", + "markdown-it-attrs": "^4.3.1", "outdent": "^0.8.0" }, "dependencies": { "@11ty/eleventy-upgrade-help": "^2.0.5", - "dotenv": "^16.0.3" + "dotenv": "^16.0.3", + "eleventy-plugin-toc": "^1.1.5" } } diff --git a/src/_includes/layouts/base.njk b/src/_includes/layouts/base.njk index 3049413..b4ee3c7 100644 --- a/src/_includes/layouts/base.njk +++ b/src/_includes/layouts/base.njk @@ -17,6 +17,9 @@ + + +${content}