Caption images with markdown render hooks in Hugo
I've been looking for a way to add captions to markdown images without falling back to raw HTML. It turns out Hugo supports this with render hooks.
thoughts and inspiration on designing, programming, and writing for the web
I've been looking for a way to add captions to markdown images without falling back to raw HTML. It turns out Hugo supports this with render hooks.
When you need to set up a service in a Laravel app, service providers are generally the place to be. But, there's one problem with service providers: they're global. This usually doesn't matter, but in multi-section apps this can be problematic.
Zipping is easy. Remembering zip
's arguments is hard.
As developers, we often talk about the importance of learning. Learning is so important to us, that it's worth persuing ways to improve the way we learn.
One way to become a better learner is to master the reverse: unlearning. Not the ability to completely forget, but the ability to set something aside for a brief moment.
When we learn a new language, framework, or tool, it's hard not to dismiss new ideas based on our existing opinions. It's the mental baggage we carry along all day.
What we've established as antipatterns in tool X's, might be shiny tool Y's bread & butter. That doesn't mean we should dismiss tool Y. Ideas on their own are rarely good or bad, they need to be evaluated in a certain context.
My colleague Brent wrote a food-for-thought post about two different kinds of programmers: builders & architects.
The first ones, the builders, are the programmers who get things done. […] On the other hand there are architects. They are concerned about sturdy and structurally sound code. […]
These two types of programmers seem like opposites. They themselves look at the other group and often think exactly that. They have a different way of handling the same problems. The other group's solutions are so different, they can't possibly be right, or so it seems.
Builders often find architects too rigid and conservative. They follow the rules for the sake of following them, without any practical benefit. Architects in turn, think of builders as careless, too focused on results, instead of thinking about long-term maintainability.
Different programmers aside, "build vs. architect" is the eternal internal conflict when I want to make decisions. Striking a balance between "getting things done" and "getting things right" is tough.
Read the entire, beautifully illustrated post on stitcher.io.
18 May 2020 via ferd.ca
By Fred Hebert:
- if you make the build tool simple, it won't handle all the weird edge cases that exist out there
- if you want to handle the weird edge cases, you need to deviate from whatever norm you wanted to establish
- if you want ease of use for common defaults, the rules for common defaults must be shared between the tool and the users, who shape their systems to fit the tool's expectations
- if you allow configuration or scripting, you give the users a way to specify the rules that must be shared, so the tool fits their systems
- if you want to keep the tool simple, you have to force your users to only play within the parameters that fit this simplicity
- if your users' use cases don't map well to your simplicity, they will build shims around your tool to attain their objectives
The endless loop of software development. Complexity is why what starts out as "a lightweight alternative to X" often ends up as bloated as X. Greenfield projects allow you to not care about the edge cases for a while, but complexity always catches up.
Read the full article on ferd.ca.
Web browsers have a few functions that accept callback parameters. setTimeout
and requestAnimationFrame
are the first that come to mind.
If you need to do multiple calls to these functions in a row, you quickly end up in callback hell. Here's a quick tip to flatten your code with async/await.
Now that we've built a dropdown list, lets add some transitions to create open & close animations.
Every now and then I do a quick checkup of a project's npm dependencies. I like to keep them up to date by often doing small upgrades. It's a lot less painful than doing large upgrades once a year.
One annoying part of this process is ensuring every dependency is on the latest major version. For example, if a project requires lint-staged@^8.0.0
, yarn upgrade
won't upgrade it to lint-staged@^9.0.0
(luckily of course, it's the behaviour I want during everyday development).
Today I learned about yarn upgrade --latest
, which will upgrade all dependencies to the highest available version, despite the version constraints in your package.json
file. lint-staged@^8.0.0
would happily upgrade to lint-staged@^9.0.0
, even if it breaks semver boundaries.
Today I set up a static documentation site (built with Hugo) for internal use. Since it contains sensitive information, I wanted to add some sort of password protection.
We don't need any dynamic user management for this, so I decided to store an encrypted password on the server with htpasswd
and enable basic authentication with nginx.
Here's how I set up basic HTTP authentication on a Laravel Forge provisioned Ubuntu server.
Confession: I don't write a lot of tests for my frontend code. This isn't something I talk about a lot because I'm scared of the pitchforks on the horizon.
I write React frontends with TypeScript. I don't don't write tests because I'm lazy, or because I don't have time, I simply don't see a lot of value in the amount of maintenance they require.
Gary Bernhardt wrote an article on how his apps are covered, and it hits the nail on the head.
We don't want tests covering most of our React components, though. That wouldn't help with the main difficulties in writing components:
- We might pass props around incorrectly. TypeScript already solves this problem for us almost completely.
- The components might use the API incorrectly. Again, we've solved this problem with TypeScript.
- The components might look wrong when rendered. Tests are very bad at this. We don't want to go down the esoteric and labor-intensive path of automated image capture and image diffing.
One thing I do write tests for is complex code that isn't coupled to components, like reducers. And the nail gets hit again:
Although we don't test components directly, there are some other parts of the frontend code that are tested directly. For example, we have some high-value tests around some React reducers because they're tricky and full of conditionals.
Read on Are Tests Necessary in TypeScript? executeprogram.com.
Last year, I added webmentions to this blog. To recap, webmentions are a web standard to create a network of comments, likes, and reposts between ordinary sites. I set up a brid.gy account to poll Twitter for webmentions targetting my blog, and I caught them with webmention.io.
Webmentions were fetched with AJAX and rendered at the bottom of each page. There were two things I didn't like about this approach:
After some tinkering, I came up with an alternative: a cron-based GitHub Action that queries webmention.io for new webmentions. The Action then commits them to my site's repository, so I can access the data with my static site generator, Hugo.
A listing of my favorite ls
features.
A short intro on my second series: Unix things I always forget!
An attempt to document the Unix commands I know and care about. Consider this series a living document that will grow organically; I won't be updating or adding new posts on a set schedule.
Every now and then I need to bump a dependency in a package, or require a higher PHP version.
{ "name": "my/package", "require": {- "php": ">=7.2.0",+ "php": ">=7.4.0",- "league/commonmark": "^0.19",+ "league/commonmark": "^1.0", } }
When updating an underlying dependency, I don't always tag a new major version. Some people consider this to be a breaking change, but it isn't. Here's how to deal with dependency and language updates from a package maintainer's perspective.