You probably already know that today, we “celebrate” April Fool’s Day. By celebrate, I mean that we watch privileged people try to imagine how they would act if they had senses of humor, generally settling on investing time in making someone else’s life more difficult. It feels like most people don’t have enough of a grasp on humor to come up with something that doesn’t amount to a transparent lie, an impediment to getting things done, or a lie that actually worries people, the last usually dismissing the harm by insisting that people should’ve known better.

Oh, I apologize. You’ll also sometimes see the fourth category, market research disguised as a prank. In this case, a company announces a “joke” product, then watches social media for people talking about how much they want it. Then, I guess that they probably think of it as a “double joke,” as they roll the product into production. Arguably, all corporate pranks have similar goals, where they care less about the joke than the opportunity for media coverage. This year, I imagine that most of them will have the backing of large language models, so try to enjoy that.

Anyway, if you don’t go in for that sort of thing, either, then Assyrians celebrate their new year, today, as Kha b-Nisan/ܚܕ ܒܢܝܣܢ or Resha d-Sheta/ܪܫܐ ܕܫܢܬܐ, the former literally today’s date and the latter translating to “the head of the year.” It connects to the Akitu festival.

Dutch officials pretending that a Moai statue washed up on shore

And with that, off we go to the projects…or do we? (There you go. Enjoy that high-class prank.)

Earburn

GitHub - jcolag/earburnBrowser extension to identify sites that accept Webmentions - jcolag/earburn

My browser extension to find sites that (at least claim to) support Webmentions has come a long way.

You can—and maybe should, if this interests you at all—review the code for the specifics. However, in broad strokes, when the current URL changes because the user has changed to a new page, then the plugin searches the HTML for any link elements with a rel property that includes a value of webmention. In the HTML, all that verbiage probably looks like this.

<link rel="webmention">

The value may have other terms in there, though, so I need to use querySelectorAll() instead of searching the code as text.

If it finds links to Webmentions, then the plugin changes its icon to have a little flame.

We can’t declare victory, though. That only works for changing the URL in the current tab, whichever tab that the user happens to currently use. Therefore, the plugin also checks when the user changes the tab, and requests a re-check of the page.

I don’t know that the icons make the change clear enough. In so few pixels, I didn’t have much room for attention-grabbing effects. But for someone actively looking at the icon for certain websites, this will work.

To the Add-ons Page…

Since it looks like the plugin works consistently, it seemed like time to figure out how to package it and get it up into the Firefox and Chrome extension pages.

You won’t see anything for this in the repository, but I zipped up all the files, named the file earburn.xpi, and…uploaded it to Mozilla. They need to put it through some sort of review process, but if all goes well, and they approve it, you can grab it for Firefox on Earburn’s Mozilla Extensions page soon.

Frankly, I consider that a huge victory, because it’ll mean that I can install an “official” version of the extension, myself, instead of using debugging actions to install from my repository. However, I do wish that they had some sort of integration with a repository; surely, Mozilla could automatically clone and zip the files as well as I can…

Does this make the first time that I’ve officially submitted (my own) software to a third party for wider distribution? I believe that it might. Mind you, I’ve certainly left code around for anybody who wants it, and put up a variety of websites over the years. I have even packaged software up—shrink-wrapped and everything—for clients who asked for it, early in my career. But as far as I can remember, this makes my first “product for general consumption,” rather than a service, one-off case, or self-service project.

I haven’t looked at the Chrome equivalent, yet, but I will at some point. If anyone has any guidance on that front, feel free to get in contact.

Entropy Arbitrage

GitHub - jcolag/entropy-arbitrage-codeThe Jekyll blog for https://john.colagioia.net/blog - jcolag/entropy-arbitrage-code

I made to additions to the blog—other than posts, I mean—this week.

First, I added a separate h-card piece, so that I can include it automatically in Webmention posts, without needing to keep track of the format. I may come to regret that, but for now, it seems like an appropriate way to go.

Second, and maybe more interesting, I created a plugin to embed one post in another. Right now, I only plan to use it for the posts that send Webmentions. But I could envision a future where I have posts that sometimes use modular components. Think of recipes, as an example, where an ingredient for one recipe might have started out as leftovers from an earlier recipe. Programming-education posts could also go this way, where I might have a set of small posts that cover common concepts, but then embed those in larger discussions of more complex ideas.

Regardless of what I might use it for in some hypothetical future, it took enough work to make it work that I should probably break it down, here.

As I’ve probably written about before, “tag” plugins have (at least) two parts, an initialize() method that can get information from the post that calls it, and a render() method that decides what to insert back into the post. In my case, initialize() doesn’t have anything interesting about it. I call the super-class’s initialization, and snag the text in the tag representing the post that I want to embed.

In render(), things get more interesting. I need to grab a ton of data to get things moving.

site = context.registers[:site]
post = site.posts.docs.find { |p| p.basename_without_ext == @post_id }
converter = site.find_converter_instance ::Jekyll::Converters::Markdown
layout = site.layouts[post.data['layout']]

Everything else uses the site information, so we definitely need that. The post variable tries to find the post whose file (minus the Markdown extension) I named after the post’s ID, something like 2024-03-29-1. Finally, converter and layout tell the plugin about converting the post from the Markdown source to HTML to insert into the published post.

If I find the right post—not a guarantee, if I mistype something—then I do the actual rendering.

content = converter.convert post.content
context.stack do
  context['page'] = Jekyll::Drops::DocumentDrop.new post
  context['content'] = content
  Liquid::Template.parse(layout.content).render context
end

I apologize for using both the terms content-with-an-n, as in the Markdown of the target post, and context-with-an-x, as in information about the post’s situation. However, this grabs that Markdown blob, and renders it using its desired layout.

I feel grateful that, when doing something like this, Jekyll doesn’t work its way up through “parent” layouts, rendering an entire HTML page inside my page. Instead, it only renders the post that I want, currently Webmentions of various sorts.

I also have more news on supporting Webmentions in general, but I’ll save this for another Wednesday Indie Web post.

Next

Given my worries that Earburn doesn’t make the presence of a Webmentions server clear enough, I may consider popping up a small window with the user’s h-card, in hopes of better making the point. And as mentioned earlier, I definitely want to work my way through the Chrome extension side, since people inexplicably still trust Google to make web browsers…

I also have some additional changes for the blog, mostly layout and styling, to push out as finalize the designs.

And I need to get back to Notoboto. And the library updates have started piling up again, already.


Credits: The header image is Beeld aangespoeld op Zandvoortse strand, made available under the terms of the Creative Commons CC0 1.0 Universal Public Domain Dedication.