update to eleventy 3.0 and a short post about it

This commit is contained in:
Robert McGovern 2024-10-18 16:26:55 +01:00
parent b28d2d96e9
commit 1c26957240
14 changed files with 3700 additions and 1964 deletions

View File

@ -9,7 +9,6 @@ const autoprefixer = require("autoprefixer");
const markdownIt = require("markdown-it"); const markdownIt = require("markdown-it");
const markdownItRenderer = new markdownIt(); const markdownItRenderer = new markdownIt();
const markdownItAnchor = require("markdown-it-anchor"); const markdownItAnchor = require("markdown-it-anchor");
// const relativeUrl = require("eleventy-filter-relative-url");
const pluginTOC = require("eleventy-plugin-toc"); const pluginTOC = require("eleventy-plugin-toc");
const moment = require("moment"); const moment = require("moment");
const description = require("eleventy-plugin-description"); const description = require("eleventy-plugin-description");
@ -17,25 +16,29 @@ const pluginRss = require("@11ty/eleventy-plugin-rss");
const UpgradeHelper = require("@11ty/eleventy-upgrade-help"); const UpgradeHelper = require("@11ty/eleventy-upgrade-help");
const xmlFiltersPlugin = require("eleventy-xml-plugin"); const xmlFiltersPlugin = require("eleventy-xml-plugin");
const yaml = require("js-yaml"); const yaml = require("js-yaml");
//const syntaxHighlight = require("@11ty/eleventy-plugin-syntaxhighlight");
const syntaxHighlight = require("eleventy-plugin-syntaxhighlight-chroma"); const syntaxHighlight = require("eleventy-plugin-syntaxhighlight-chroma");
const highlight = require("chroma-highlight"); const highlight = require("chroma-highlight");
const eleventySass = require("@11tyrocks/eleventy-plugin-sass-lightningcss"); const eleventySass = require("@11tyrocks/eleventy-plugin-sass-lightningcss");
const inspect = require("node:util").inspect; const inspect = require("node:util").inspect;
// relativeURL
const path = require("path"); const path = require("path");
const urlFilter = require("@11ty/eleventy/src/Filters/Url");
const { assert } = require("console"); module.exports.config = {
pathPrefix: "/",
};
module.exports = async function (eleventyConfig) {
// const urlFilter = await import("@11ty/eleventy/src/Filters/Url");
const indexify = (url) => url.replace(/(\/[^.]*)$/, "$1index.html"); const indexify = (url) => url.replace(/(\/[^.]*)$/, "$1index.html");
module.exports = function (eleventyConfig) {
let pathPrefix = "/"; let pathPrefix = "/";
eleventyConfig.addDataExtension("yaml", (contents) => yaml.load(contents)); eleventyConfig.addDataExtension("yaml", (contents) => yaml.load(contents));
eleventyConfig.addDataExtension("yml", (contents) => yaml.load(contents)); eleventyConfig.addDataExtension("yml", (contents) => yaml.load(contents));
// eleventyConfig.addPlugin(UpgradeHelper);
eleventyConfig.addPlugin(pluginRss); eleventyConfig.addPlugin(pluginRss);
//Blog excerpts //Blog excerpts
eleventyConfig.addPlugin(description); eleventyConfig.addPlugin(description);
@ -226,6 +229,11 @@ module.exports = function (eleventyConfig) {
return inspect(obj, { sorted: true }); return inspect(obj, { sorted: true });
}); });
eleventyConfig.addFilter("debugger", (...args) => {
console.log(...args);
debugger;
});
eleventyConfig.addFilter("group_by", groupBy); eleventyConfig.addFilter("group_by", groupBy);
eleventyConfig.addLayoutAlias( eleventyConfig.addLayoutAlias(
@ -399,7 +407,12 @@ module.exports = function (eleventyConfig) {
// eleventyConfig.addWatchTarget("dist/assets/css/*.css"); // eleventyConfig.addWatchTarget("dist/assets/css/*.css");
eleventyConfig.addFilter("relative_url", relativeURLALT); const { EleventyHtmlBasePlugin } = await import("@11ty/eleventy");
eleventyConfig.addPlugin(EleventyHtmlBasePlugin);
eleventyConfig.addFilter("relative_url", relativeURLALT2);
eleventyConfig.addFilter("absolute_url", absoluteUrl); eleventyConfig.addFilter("absolute_url", absoluteUrl);
return { return {
@ -427,90 +440,12 @@ function numberOfWords(content) {
return content.split(/\s+/g).length; return content.split(/\s+/g).length;
} }
function relativeURL(url, pathPrefix = undefined) { // Cheat till I can go through
if (pathPrefix !== undefined) { function relativeURLALT2(url) {
// Fall back on original url filter if pathPrefix is set. if (!url.startsWith("/")) {
return urlFilter(url, pathPrefix); throw new Error("URL is already relative");
} }
return url;
if (pathPrefix == undefined && this.page == undefined) {
return urlFilter(url, "");
}
// Look up the url of the current rendering page, which is accessible via
// `this`.
//console.log(this); // rmcg
// rmcg - removed ctx from this.ctx.page.url
const currentDir = this.page.url;
const filteredUrl = urlFilter(url, "/");
// Make sure the index.html is expressed.
const indexUrl = indexify(filteredUrl);
// Check that the url doesn't specify a protocol.
const u = new URL(indexUrl, "make-relative://");
if (u.protocol !== "make-relative:") {
// It has a protocol, so just return the filtered URL output.
return filteredUrl;
}
// Return the relative path, or `index.html` if it's the same as the current
// page's directory.
const relativePath = `${
path.relative(currentDir, u.pathname) || "index.html"
}`;
return relativePath;
}
/**
* Just `{{ '/something' | url }}` will return the relative path to
* `/something/index.html`.
*
* `{{ '/something.with.dots' | url }}` will return the relative path to
* `/something.with.dots`.
*
* @param {string} url the URL to transform
* @param {string} [pathPrefix] optional path prefix to force an absolute URL
* @returns {string} resulting URL
*/
function relativeURLALT(url, pathPrefix = undefined) {
pathPrefix = "/";
// console.log(url);
// console.log(pathPrefix);
// console.log(this.page);
if (pathPrefix !== undefined) {
// Fall back on original url filter if pathPrefix is set.
return urlFilter(url, pathPrefix);
}
if (pathPrefix == undefined && this.page == undefined) {
// console.log("dropping out");
return urlFilter(url, "");
}
// Look up the url of the current rendering page, which is accessible via
// `this`.
console.log(this);
const currentDir = this.page.url;
const filteredUrl = urlFilter(url, "/");
// Make sure the index.html is expressed.
const indexUrl = indexify(filteredUrl);
// Check that the url doesn't specify a protocol.
const u = new URL(indexUrl, "make-relative://");
if (u.protocol !== "make-relative:") {
// It has a protocol, so just return the filtered URL output.
return filteredUrl;
}
// Return the relative path, or `index.html` if it's the same as the current
// page's directory.
const relativePath = `${
path.relative(currentDir, u.pathname) || "index.html"
}`;
return relativePath;
} }
function absoluteUrl(url) { function absoluteUrl(url) {

5214
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -27,13 +27,13 @@
"author": "Robert McGovern et all", "author": "Robert McGovern et all",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@11ty/eleventy": "^2.0.0" "@11ty/eleventy": "^3.0.0"
}, },
"dependencies": { "dependencies": {
"@11ty/eleventy-navigation": "^0.3.5", "@11ty/eleventy-navigation": "^0.3.5",
"@11ty/eleventy-plugin-rss": "^1.2.0", "@11ty/eleventy-plugin-rss": "^1.2.0",
"@11ty/eleventy-plugin-syntaxhighlight": "^4.2.0", "@11ty/eleventy-plugin-syntaxhighlight": "^4.2.0",
"@11ty/eleventy-upgrade-help": "^2.0.5", "@11ty/eleventy-upgrade-help": "^3.0.1",
"@11tyrocks/eleventy-plugin-sass-lightningcss": "^1.0.0", "@11tyrocks/eleventy-plugin-sass-lightningcss": "^1.0.0",
"autoprefixer": "^10.4.13", "autoprefixer": "^10.4.13",
"chroma-highlight": "^2.4.2", "chroma-highlight": "^2.4.2",

View File

@ -32,7 +32,8 @@
<p class="archive__item-excerpt" itemprop="description">{{ include.aPost.data.excerpt | markdownify | strip_html | truncate: 160 }}</p> <p class="archive__item-excerpt" itemprop="description">{{ include.aPost.data.excerpt | markdownify | strip_html | truncate: 160 }}</p>
{% else %} {% else %}
<!-- RMCG - Result of this isn't perfect but it works, so now all posts show an excerpt of sorts --> <!-- RMCG - Result of this isn't perfect but it works, so now all posts show an excerpt of sorts -->
<p class="archive__item-excerpt" itemprop="description">{{ include.aPost.template._frontMatter.content strip_html | markdownify | truncate: 160 }}</p> <p class="archive__item-excerpt" itemprop="description">{{ include.aPost.template._cacheRenderedPromise |
markdownify | strip_html | truncate: 160 }}</p>
{% endif %} {% endif %}
</article> </article>

View File

@ -1,5 +1,5 @@
{% assign document = post | default: page %} {% assign document = post | default: page %}
{% assign document = document.data.page %} <!-- {% assign document = document.data.page %} -->
{% if document.read_time or document.show_date or site.defaults.posts.show_date %} {% if document.read_time or document.show_date or site.defaults.posts.show_date %}
@ -20,7 +20,18 @@
{% assign con = include.content | default: content %} {% assign con = include.content | default: content %}
{% assign words = con | strip_html | number_of_words %} {% assign words = con | strip_html | number_of_words %}
<!-- There is a minute difference between the time to read on the list pages, and on the article itself. So 5 minutes to read in the list, 4 minutes to read on article itself --> <!-- RMCG Hack to be able to have the time to read the article on both the index page, and the article itself. However there can be minor disparaties -->
{% if words == 1 %}
{% assign con = document.rawInput %}
{% if con %}
{% assign con = con | markdownify | strip_html %}
{% endif %}
{% assign words = con | strip_html | number_of_words %}
{% endif %}
<!-- There is a minute difference between the time to read on the list pages, and on the article itself. So 4 minutes to read in the list, 5 minutes to read on article itself -->
<span class="page__meta-readtime"> <span class="page__meta-readtime">
<i class="far {% if include.type == 'grid' and document.read_time and document.show_date %}fa-fw {% endif %}fa-clock" aria-hidden="true"></i> <i class="far {% if include.type == 'grid' and document.read_time and document.show_date %}fa-fw {% endif %}fa-clock" aria-hidden="true"></i>

1
src/_posts/.obsidian/app.json vendored Normal file
View File

@ -0,0 +1 @@
{}

3
src/_posts/.obsidian/appearance.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"accentColor": ""
}

View File

@ -0,0 +1,30 @@
{
"file-explorer": true,
"global-search": true,
"switcher": true,
"graph": true,
"backlink": true,
"canvas": true,
"outgoing-link": true,
"tag-pane": true,
"properties": false,
"page-preview": true,
"daily-notes": true,
"templates": true,
"note-composer": true,
"command-palette": true,
"slash-command": false,
"editor-status": true,
"bookmarks": true,
"markdown-importer": false,
"zk-prefixer": false,
"random-note": false,
"outline": true,
"word-count": true,
"slides": false,
"audio-recorder": false,
"workspaces": false,
"file-recovery": true,
"publish": false,
"sync": false
}

20
src/_posts/.obsidian/core-plugins.json vendored Normal file
View File

@ -0,0 +1,20 @@
[
"file-explorer",
"global-search",
"switcher",
"graph",
"backlink",
"canvas",
"outgoing-link",
"tag-pane",
"page-preview",
"daily-notes",
"templates",
"note-composer",
"command-palette",
"editor-status",
"bookmarks",
"outline",
"word-count",
"file-recovery"
]

157
src/_posts/.obsidian/workspace.json vendored Normal file
View File

@ -0,0 +1,157 @@
{
"main": {
"id": "3efdf9896e8f8d7d",
"type": "split",
"children": [
{
"id": "d350c113c8a17ee4",
"type": "tabs",
"children": [
{
"id": "20fb08ab7da8ab29",
"type": "leaf",
"state": {
"type": "markdown",
"state": {
"file": "outline-border-radius.md",
"mode": "source",
"source": false
}
}
}
]
}
],
"direction": "vertical"
},
"left": {
"id": "a90ae722eee9662a",
"type": "split",
"children": [
{
"id": "a075e922725f738d",
"type": "tabs",
"children": [
{
"id": "83e57e3705c02e99",
"type": "leaf",
"state": {
"type": "file-explorer",
"state": {
"sortOrder": "alphabetical"
}
}
},
{
"id": "36a2573a0eb5690e",
"type": "leaf",
"state": {
"type": "search",
"state": {
"query": "",
"matchingCase": false,
"explainSearch": false,
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical"
}
}
},
{
"id": "c7f023012b3bf67f",
"type": "leaf",
"state": {
"type": "bookmarks",
"state": {}
}
}
]
}
],
"direction": "horizontal",
"width": 300
},
"right": {
"id": "1002ff2537d85cb3",
"type": "split",
"children": [
{
"id": "b973022c94fd3ea2",
"type": "tabs",
"children": [
{
"id": "59225b743243f34a",
"type": "leaf",
"state": {
"type": "backlink",
"state": {
"file": "outline-border-radius.md",
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical",
"showSearch": false,
"searchQuery": "",
"backlinkCollapsed": false,
"unlinkedCollapsed": true
}
}
},
{
"id": "7c323d6a34b49662",
"type": "leaf",
"state": {
"type": "outgoing-link",
"state": {
"file": "outline-border-radius.md",
"linksCollapsed": false,
"unlinkedCollapsed": true
}
}
},
{
"id": "9ab719731ae718a4",
"type": "leaf",
"state": {
"type": "tag",
"state": {
"sortOrder": "frequency",
"useHierarchy": true
}
}
},
{
"id": "4e304b46b09b10e8",
"type": "leaf",
"state": {
"type": "outline",
"state": {
"file": "outline-border-radius.md"
}
}
}
]
}
],
"direction": "horizontal",
"width": 300,
"collapsed": true
},
"left-ribbon": {
"hiddenItems": {
"switcher:Open quick switcher": false,
"graph:Open graph view": false,
"canvas:Create new canvas": false,
"daily-notes:Open today's daily note": false,
"templates:Insert template": false,
"command-palette:Open command palette": false
}
},
"active": "20fb08ab7da8ab29",
"lastOpenFiles": [
"2023-02-19-copy-code-blocks.md",
"2022-10-15-frontend-mentor-challenge-deployment.md",
"2023-01-21-moving-blog.md",
"2023-01-26-site-moved.md",
"2019-02-21-first-post.md"
]
}

View File

@ -0,0 +1,72 @@
---
title: An Needless Exercise in frustration Eleventy 2.x -> 3.0
description: ""
date: 2024-10-18T13:13:03.320Z
preview: ""
tags: [site, personal]
category: [site, personal]
excerpt: A frustrating update to 11ty / Eleventy 3.0 release, esp when I plan to switch to Astro
layout: single
---
For reasons of sanity, or insanity really, I figured I might as well update the mechanics of the blog From Eleventy 2.x to the fresh and shiny new 3.0. I figured it couldn't hurt too much surely.
Boy was I wrong!
And unfortunately, I didn't take extensive notes as I went along. One of the issues stemmed from having not swapped to `pathPrefix` when v2 came along. Instead I had been using a 3 year old npm eleventy plugin to get relative urls.
It was loading this particular filter: `const urlFilter = require("@11ty/eleventy/src/Filters/Url");`
But this caused the build to fail
```autodetect
[11ty] File changed: .eleventy.js
[11ty] Eleventy watch error:
[11ty] 1. Error in your Eleventy config file '.eleventy.js'. (via EleventyConfigError)
[11ty] 2. Package subpath './src/Filters/Url' is not defined by "exports" in /Users/tarasis/Programming/Websites/tarasis.net/node_modules/@11ty/eleventy/package.json imported from /Users/tarasis/Programming/Websites/tarasis.net/.eleventy.js
[11ty]
[11ty] Original error stack trace: Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './src/Filters/Url' is not defined by "exports" in /Users/tarasis/Programming/Websites/tarasis.net/node_modules/@11ty/eleventy/package.json imported from /Users/tarasis/Programming/Websites/tarasis.net/.eleventy.js
[11ty] at exportsNotFound (node:internal/modules/esm/resolve:296:10)
[11ty] at packageExportsResolve (node:internal/modules/esm/resolve:643:9)
[11ty] at packageResolve (node:internal/modules/esm/resolve:822:14)
[11ty] at moduleResolve (node:internal/modules/esm/resolve:908:18)
[11ty] at defaultResolve (node:internal/modules/esm/resolve:1038:11)
[11ty] at nextResolve (node:internal/modules/esm/hooks:748:28)
[11ty] at resolve (file:///Users/tarasis/Programming/Websites/tarasis.net/node_modules/@11ty/eleventy/src/Util/EsmResolver.js:25:11)
[11ty] at nextResolve (node:internal/modules/esm/hooks:748:28)
[11ty] at Hooks.resolve (node:internal/modules/esm/hooks:240:30)
[11ty] at handleMessage (node:internal/modules/esm/worker:199:24)
```
It was fine, I had already taken the code from the plugin and had put it into my `.eleventy.js`, so I figured I could swap it over to the new `await import` for @11ty stuff. Quick modified `module.exports = async function (eleventyConfig) {}` and moved `const urlFilter = await import("@11ty/eleventy/src/Filters/Url");` into that async function.
Tried again and got the same error.
Googling on the `require("@11ty/eleventy/src/Filters/Url");` brings up precisely 2 posts. Which was pretty impressive. One from 2020, the other from 2021. So nothing useful. You could previously use it, and now you couldn't ([it (Url.js)](https://github.com/11ty/eleventy/blob/main/src/Filters/Url.js) is still there, exported by [defaultConfig.js](https://github.com/11ty/eleventy/blob/main/src/defaultConfig.js))
![Image showing precisely 2 hits](/assets/images/posts/2hits.png)
So this lead me back around to looking at 11ty and URLS, looking at how other people had done relative urls with 11ty and a bunch of debugging and seeing what URLS where being generated, I then discovered `pathPrefix` and the HTML base plugin 😡
So in `.eleventy.js` I now return the URL right back out
```js
// Cheat till I can go through
function relativeURLALT2(url) {
if (!url.startsWith("/")) {
throw new Error("URL is already relative");
}
return url;
}
```
Why you may wonder, because I don't overly fancy find and replacing `| relative_url }}` 52 times. Especially as I was planning on starting from scratch with Astro.js and having a go at making something more whimsical.
But once I start the upgrade process, I needed to get it working. Plus side it means that I've managed to fix/hack it to that the "correct"[^1] time while now show (with added caveat that it assumes reading at 200 words a minute), and have excerpts generated for older posts that don't have them in the front matter (aka most of them)
![Image of a post on the front page, below the title of is the date it was published, and a small clock icon and a number of minutes](/assets/images/posts/post-date-and-reading-time.png)
I have one issue that remains but I'm not going to fret about it for the moment, the way I have sass set up sometimes means a needed file hasn't been copied over when the sass compile happens, which breaks the compile and no CSS. I will deal with it, but for now I'd rather put the effort into v5 of the much under used TDN Site/Blog
[^1]: Its fair to say there is an inaccuracy between the index page and what you'll see on the post itself. Its usually off by a minute, with no real guarantee which is more accurate. The data being passed into page_meta.html is different if it comes from a post layout, vs what it gets at the time the pagination is generated. I had it turned off on the index pages because it was say 1 min for all articles.

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

View File

@ -7,9 +7,9 @@ pagination:
--- ---
{%- for post in pagination.items -%} {%- for post in pagination.items -%}
<h2><a href="{% post_url post.fileSlug %}">{{ post.data.title }}</a></h2>
<em>{{ post.data.date | toUTCString}}</em> {% include archive-single.html type=entries_layout aPost=post %}
<p>{{ post.templateContent | description }} <a href="{% post_url post.fileSlug %}"><em>read more</em></a></p>
{%- endfor -%} {%- endfor -%}