Better way to indent ordered lists in Markdown
Published on in Markdown
1. foo
is annoying because the list item's text is indented with three spaces.
Solution: add another space after the period.
A collection of my wildest adventures with computers. Mostly about web development.
Published on in Markdown
1. foo
is annoying because the list item's text is indented with three spaces.
Solution: add another space after the period.
Published on in Bookmarklets and JavaScript
There's no built-in way to preview HTML files on GitHub, but you can use this nifty bookmarklet. (GitHub's project managers HATE it!)
Content-Type: "application/json"
Published on in JavaScript, Node.js and TypeScript
If you are sending a FormData
body with fetch
,
things might not work correctly if you are (accidentally)
setting the Content-Type
request header to "application/json"
.
position: relative
on <tr>
elementsThis is a problem if you want whole table rows to be clickable. Luckily there's a (hacky) workaround.
Published on in English
I came up with this acronym myself, and I'm proud of it!
Published on in Miscellaneous
Alternative title: How to fix the "Failed to load MSAL4J Java library for performing ActiveDirectoryPassword authentication" error.
mailto:
links with target="_blank"
are surprisingly trickyPublished on in JavaScript
Only because Firefox ignores target="_blank"
in mailto:
links.
Published on in Miscellaneous
Make sure you are not missing two empty lines after the request headers. There's a UX lesson here.
Published on in Games
I managed to find time to play Desperados III and Lost in Play (and Before Your Eyes too a bit).
Published on in Books
I started a new hobby in 2023: reading fiction books! I started with fantasy: Harry Potter, Mistborn, and The Stormlight Archive.
Published on in Miscellaneous
Use the :style()
operator in a uBlock Origin filter
to apply CSS styles to the targeted elements.
Published on in Handlebars and SendGrid
There's a way to do an "else equals" check in Handlebars (in SendGrid's Dynamic Templates), though it's undocumented and a bit tricky.
Published on in Miscellaneous
I sometimes forget what these two headers do in requests vs responses, so here's a refresher for me.
Published on in Mac
The longer Firefox is kept open, the longer it takes for Firefox to receive focus after Cmd-tabing to it. At some point it can take even about a second, which really kills the flow.
Published on in JavaScript
It's too easy to accidentally import a default export with a misleading name.
Published on in JavaScript and TypeScript
Let's learn about anti-symmetry by solving this interview puzzle: "Move all zeros of an array of integers to the end while maintaining the relative order of all non-zeros."
Published on in JavaScript
There's apparently no nice way to bulk-log hours in Jira. Use this One Weird Trick to do it anyway – Jira consultants HATE it!
Published on in Miscellaneous
In a perfect world, minor- and patch-level version bumps don't have breaking changes. In the real world, things are complicated and shit happens.
error.cause
needs to be logged manually to App InsightsPublished on in JavaScript
If you are logging errors to Azure App Insights,
and an Error object has a cause
property (which too could be an Error object),
the cause
Error's message
and stack
properties are not shown in Azure App Insights.
But you can log them manually.
\d
in a regex isn't always equal to [0-9]
Published on in JavaScript and Regular expressions
In JavaScript, \d
and [0-9]
are equal and match only Arabic numerals (the numbers 0–9).
But in some other languages, \d
matches also non-Arabic numerals.
response.json()
can throw an error in JavaScriptPublished on in JavaScript
If the response body is not valid JSON,
response.json()
will throw,
just like JSON.parse()
would throw
if the same data was passed to it.
error.stack
includes the error message in some JS environmentsPublished on in JavaScript
Last updated on
In V8-based JS environments (e.g. Chrome, Deno and Node.js) and in Bun,
error.stack
= error class name + error.message
+ stack frames.
yarn install
failing mysteriously on Node.js v18.18Published on in JavaScript
Last updated on
TL;DR: Upgrading Yarn from v1 to v4 fixed it for me.
Published on in JavaScript and Mnemonics
When sorting an array with a custom comparator function,
the function should return <0
, 0
or >0
.
But what do the values do?
Use this weird visual mnemonic –
sorting consultants HATE it!
Published on in JavaScript, TypeScript and Zod
Alternative title:
I finally found a good use case for z.object().strict()
in Zod.
Published on in ESLint, JavaScript and TypeScript
Last updated on
Node-Cache (a JS library) has generic get
and set
methods,
but it's easy to accidentally misuse them.
I made a type-safer wrapper around the library.
Published on in Miscellaneous
Incidentally, it's also great for searching for certain words in a video.
Published on in Bookmarklets and JavaScript
Quick and dirty code to grab a single frame of a YouTube video. Might work with other video players too.
Published on in Miscellaneous
Legacy code means unfamiliar code. Legacy code has much more to do with unfamiliarity than the quality of the code itself.
Date
objects are nicer to work with than date stringsPublished on in JavaScript, TypeScript and Zod
When parsing data,
date strings should likely be converted to Date
objects.
But beware mutations.
Published on in Books
I don't know if I have ever read so much in so short time. I just liked the books so much.
Published on in JavaScript, Joi, TypeScript and Zod
Last updated on
Parsing encompasses validation, plus it can increase type-safety, plus it can transform the data to a better format. Parse, don't just validate.
Published on in Books
MOBI is an old e-book format. AZW3 is a newer and apparently better format; for instance, it supports embedded fonts. Here's how to configure Calibre to prefer the better format.
Published on in Books
Last updated on
A reminder for myself how to make library e-books pleasant to use with the help of Calibre and two Calibre plugins.
Published on in JavaScript and SendGrid
If you send a single email to a bunch of email addresses, and some of the addresses are aliases, i.e. they point to the same email inbox, chances are high that only one copy of the email is delivered to that inbox.
Mindlessly surfing the internet is like staring at the Mirror of Erised from the Harry Potter books. (Minor Harry Potter spoilers ahead.)
Published on in Miscellaneous
This 16-minute video by Henrik Kniberg is a great overview of the agile software development process, but also contains lots of smaller great insights.
Published on in Books
Tiny good things accumulate into great things. Tiny bad things accumulate into horrible things. This book tells you how to do more of those good things and less of those bad things.
Published on in Battlestation
Last updated on
After 2.5 years of using a 120 cm wide super ultrawide computer monitor with a 32:9 aspect ratio, I'm back to a boring 64 cm wide 16:9 monitor. The smaller monitor now feels better in every regard.
Published on in Blogging
"Weekly log" basically meaning weekly blog posts with a specific structure. Today I removed the whole Weekly log.
Published on in Mac
I have used Windows PCs since I was a kid. A year ago (Jan 2022) I got my first MacBook. While Mac isn't perfect, it's so much better that I'm not going back to Windows.
Published on in JavaScript and TypeScript
Last updated on
A little helper function to retry a function automatically a limited number of times (or until success) and with a certain delay between retries. Useful e.g. when working with a flaky API.
Published on in JavaScript and React
Last updated on
If I'm already displaying data that I have successfully fetched with SWR, and then another fetch call fails (when revalidating the data), I don't want to replace the data view with an error view. Here's how to avoid that.
Published on in Work–life balance
Care less, take a sabbatical, get a second job, get monster ear protection, hide behind your manager.
React.forwardRef
Published on in JavaScript and React
A component wrapped in React.forwardRef
normally expects to receive a ref from its parent component.
What if you want the component to have a ref
even if it doesn't receive one from its parent?
Published on in Cool tools
I'm looking for a software that does 2-way syncing between my MacBook's hard drive and an external hard drive. Syncthing vs rsync vs Unison vs FreeFileSync vs Resilio Sync... oh my!
Published on in Git
git stash -k
doesn't work as expected.
Use a temporary commit instead.
Published on in JavaScript
"Given an array of coins and a target amount, return all combinations of coins that add up to the amount, or an empty array if no such combinations exist."
Published on in Clean code and JavaScript
For example, mutating a reducer function's accumulator array can be better than religiously avoiding mutations and returning only new arrays from the reducer.
Published on in JavaScript
Last updated on
That's because it would take a very long time, and at some point you would have so many permutations that they wouldn't fit in an array.
Published on in JavaScript
Last updated on
Example:
converting [1, 2, 3]
into [[1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
.
Published on in Miscellaneous
Most chat apps have an "unread" message state to keep track of messages I haven't read yet. Why isn't there a different state for messages I haven't replied to yet?
Published on in Cool tools, English and VS Code
Doesn't only look for typos but for grammar and style issues as well. Not to be confused with LaTeX.
Published on in Sleep
I recently switched from linen bedclothes (sheets, pillowcases, duvet covers) back to cotton bedclothes – bad idea. My sleep quality took a drastic hit.
Automatically updating a private Git submodule before builds is convenient but requires some setup.
Published on in JavaScript
Instead of spending 5 minutes to look for and use an existing mortgage calculator, I wasted time figuring out how to do the calculations from scratch.
Published on in JavaScript and TypeScript
Huh. But if the array has 2+ items, attempting to sort it will cause a TypeError.
Say "n" and cluck and relax. Easy! Correct tongue position makes nasal breathing easier.
Jogging is one type of running. When I run, I mostly jog, but I still think I'm a runner, not a jogger. Huh?
Published on in NoSurf
A trouser pocket is way too easily reachable. I often find myself reaching for my phone automatically even if I don't have anything to do with the phone.
useReducer
Published on in JavaScript and React
Say goodbye to useState
and a silly toggler function calling the state setter.
Be cool and use a tiny reducer instead.
Published on in JavaScript, Mithril.js and React
AutoAnimate is a JS library that provides simple animations with no effort. Works with Mithril.js, React and any other JS app.
type="button"
Published on in JavaScript, React and TypeScript
A <button>
element defaults to type="submit"
which can cause accidental form submissions.
Make type="button"
the default in your Button component
to make your life easier.
Published on in JavaScript and TypeScript
The TypeScript compiler could help prevent "illegal invocation" errors at compile time, at least theoretically.
dangerouslySetInnerHTML
Published on in JavaScript, React and TypeScript
Last updated on
To handle internal link clicks when using dangerouslySetInnerHTML
,
attach click event listeners to the rendered links.
In the listener, push the link to the browser history.
conditional()
Published on in JavaScript, Joi and Testing
Last updated on
Use { is: Joi.any().valid(...values) }
to check if a value is included in an array.
.mts
is a cool file extension (TypeScript ES modules)Published on in JavaScript, Node.js and TypeScript
What's that, a file extension named after me?! Or a file extension for TypeScript files that are always ES modules?
Published on in JavaScript and React
React is marketed as a view library, but it's more accurately a (view component) framework.
compose()
is right-to-leftPublished on in JavaScript
Functions composed together with compose()
are called from right to left.
It feels unintuitive at first,
but it's conventional
and kind of makes sense.
Published on in English
Like so: "The name's Bourne," the man said, "JSON Bourne." Also when quoting single words, like "nibbles," "gronk" and "fleebles."
Published on in JavaScript, Mithril.js, Rant and React
Last updated on
React's ecosystem is large, which is a good thing: lot's of great libraries to use. But it's also a bad thing: most of those libraries are compatible only with React.
Published on in Work–life balance
Try to schedule vacations so that they start and end in the middle of the week. You'll get two short work weeks around the vacation.
Published on in JavaScript and React
Last updated on
HTM provides a transpiler-free alternative to JSX via tagged templates. HTM has some limitations, but can be used in browsers and can be good for smaller projects.
Published on in JavaScript
Fun way to solve the simple puzzle.
Infinitely repeating arrays
and mapping over multiple arrays
almost makes the remainder/modulo operator (%
) unnecessary.
Published on in JavaScript and TypeScript
Using recursion,
logical OR assignment operator (||=
),
BigInts
and more!
Published on in Eleventy
The two names are often used interchangeably, but there's a slight difference: 11ty is the organization, Eleventy is the static site generator.
Published on in Episerver, JavaScript and React
Last updated on
Also known as Episerver/Idio Content Recommendations. The usual way of using a Mustache template can be circumvented by using a JavaScript proxy.
Or any other automatic periodic builds. I'm using daily builds to automatically publish scheduled blog posts on my Eleventy site.
Published on in JavaScript and Node.js
Last updated on
Say goodbye to ../
times million
and use absolute import paths from the app's root directory instead.
Two contenders: Basetag and Sultan's sexy-require
! 🤺
Published on in Testing
Last updated on
Smoke testing is cursory or "quick and dirty" testing to see that the software works correctly.
Published on in JavaScript, React and TypeScript
Last updated on
I.e. props that depend on other props. You can require and forbid certain prop combinations by utilizing TypeScript's union and intersection types.
Published on in Accessibility
Last updated on
Five simple rules for using ARIA attributes, straight from W3C.
Published on in Blogging
Last updated on
I ditched my website's Cookbook section and converted existing recipes to blog posts. Mostly to reduce stress and make things clearer.
Use these weird tricks to remember which words are American English and which are British English. Linguists HATE them!
Published on in Cool tools and SVG
A squircle is a rounded square with no straight edges; the shape is a continuous curve.
Published on in Miscellaneous
I kayaked for the first time in my life and quite liked it. Then I ate pizza.
useStateMachine
: ½ kB state machine hook for ReactPublished on in JavaScript and React
A state machine is a bit like useReducer
,
but with greater constraints (in a good way).
This state machine hook is tiny.
Published on in Miscellaneous
A daily stand-up should focus on the sprint. But it should also be about the team members.
Published on in Clojure
It's not mentioned in the docs or anywhere, but you can enable Parinfer from Cursive's settings. Works great with IdeaVim.
Published on in JavaScript and React
A common solution is to scroll to top every time the page changes. That's incorrect: the page should be scrolled to top only when navigating to new pages, not when navigating back or forward.
<strong>
and <em>
should be treated as progressive enhancementPublished on in Accessibility
Screen readers don't announce emphasized text, so your text should be understandable even without the emphases.
Action
vs Func
vs Predicate
Published on in C#
Last updated on
Action
doesn't return anything,
Func
does.
Predicate
takes one parameter and returns a boolean.
Published on in Miscellaneous
If you append a comment (like # foo
) to a terminal command,
you can search by the comment text when using Ctrl+R.
Published on in Clean code, Documentation and Markdown
A paragraph per line, a sentence per line, or hard wrapping at e.g. 80 characters? These days I prefer a fourth option: semantic line breaks.
Published on in JavaScript and React
Normally you would use one-way data binding in React apps: parent components own data and pass it to children. You can mimic two-way data binding with a custom hook.
Published on in Clean code, JavaScript and React
Last updated on
A multi-site React project has likely two kinds of components: common components and site-specific components. There are a few ways to handle site-specific logic in common components.
Published on in ESLint and JavaScript
There's an ESLint rule to prevent importing certain files in certain folders. I needed this in a multi-site project to prevent importing site-specific components in other sites' folders.
Published on in Battlestation
Maybe a bit of an overkill, but much more convenient than using my iPad as a webcam or my laptop's integrated webcam.
Published on in Miscellaneous
That cool thing you just heard about – is it suddenly gaining popularity, or are you just noticing the topic more?
margin: auto
Published on in CSS and CSS for JS Devs course
margin: auto
is not only for horizontal centering.
position: fixed
breaks if any of its ancestors uses transform
Published on in CSS and CSS for JS Devs course
Or perspective
or filter
.
This can easily cause confusing bugs.
length
propertyPublished on in JavaScript
Last updated on
A bit exotic, but can be useful for currying.
Published on in CSS and CSS for JS Devs course
height
and width
work somewhat differently in CSS.
height
looks "down" the tree
whereas width
looks "up" the tree.
Published on in CSS and CSS for JS Devs course
Block elements stack on top of each other. Inline elements are placed side by side.
Published on in JavaScript, React and Testing
React context is normally updated inside the React app. Here's a hacky way how I circumvented that restriction in a test file.
Published on in Excel
For example, 6 hours is stored as 0.25 days.
To format a duration as hh:mm:ss.000
,
first convert the duration to days.
Published on in Safari
Try to add object-src 'self';
to the Content Security Policy.
Then your users don't have to download the file to view it.
Some parts of an SVG were missing and some parts were distorted.
I had to render the SVG via an <svg>
element
instead of loading it via an <img>
element.
Published on in CSS and CSS for JS Devs course
Last updated on
It's frustrating when a CSS declaration is technically valid (not crossed out in the browser's DevTools) but has no effect for some reason. Firefox DevTools can often tell you why and also how to potentially fix those issues! (Update: Chrome 108+ can too.)
Published on in Documentation
Last updated on
Splitting documentation into multiple categories can make the documentation much clearer.
Published on in JavaScript and TypeScript
"Parameter properties" reduce boilerplate in classes, but they can also make the code hard to read.
Published on in JavaScript
Spoiler:
new Date(year, 1, 29).getDate() === 29
.
The NSubstitute package simplifies how mock implementations are created and how mocks are used.
The Fluent Assertions package makes unit test assertions read like English and also improves the error messages.
Disabling the upscaling feature (by default or completely)
can be done via ImageProcessor's ValidatingRequest
event.
It's not possible via a config file.
YouTube recommended me a two-part video series that was fun to watch and gave me a few lightbulb thoughts.
will-change
propertyPublished on in CSS
The will-change
property makes the browser render an element with the GPU,
which can reduce jankiness and also allows utilizing sub-pixel rendering.
But use the property sparingly.
display: flow-root
is better than the clearfix hackPublished on in CSS
The flow-root
value is clearer (no hacks!)
and has great browser support.
Published on in CSS
Polish your animations by animating based on actions or events, like mouse-enter and mouse-leave, instead of animating based on states, like default and hover state.
as
and is
operatorsA cast expression like (string)foo
throws
if the types don't match.
The as
operator doesn't throw
and defaults to null
.
The is
operator doesn't throw
and ignores null
s.
Published on in JavaScript, React and Testing
Such naming helps you create tests that resemble the way your users use your app.
Blocks in Episerver implement the IContent
interface only during runtime
which makes using AutoMapper difficult.
Published on in Accessibility, JavaScript, React and Testing
Accessible queries take into account the semantic meaning of HTML elements. Such queries help you write more accessible apps.
Both are guesses. Assume is weaker (little or no evidence), presume is stronger (reasonable evidence). But how to remember which is which?
npx cloc
Published on in Cool tools
Last updated on
Run npx cloc [options] <files/dirs>
.
E.g. npx cloc src/
or npx cloc foo.js bar.css
.
Published on in Bookmarklets
Last updated on
Use a bookmarklet to stop Plausible Analytics from counting your own visits made using mobile devices.
Published on in JavaScript and Mithril.js
Last updated on
Create a DocumentFragment
and render the component to it.
Then there's no need to mount the component to the DOM.
Published on in SVG
Last updated on
Creating icons and simple figures by handcrafting SVG code is not as hard as it sounds.
Published on in JavaScript and Mithril.js
Last updated on
Disable auto-redraw with event.redraw = false
and use a timeout.
Published on in JavaScript and Mithril.js
Last updated on
m.nest('ul > li', 'Item')
can be achieved with reduceRight()
.
Published on in Regular expressions
Last updated on
Greedy quantifiers (the default, e.g. *
) match as much as possible.
Lazy quantifiers (e.g. *?
) match as little as possible.
Intl.ListFormat
Published on in JavaScript
Last updated on
Pass an array of strings and get back a string with the array items separated by commas, except with the last comma replaced with the word "and" or "or." Like "item 1, item 2 and item 3."
Published on in Episerver, JavaScript and React
Thoughts on how to efficiently use React to render Episerver blocks embedded in TinyMCE fields.
Published on in JavaScript
Last updated on
Run JSON.stringify(object, null, 2)
.
Adjust the number for a different level of indentation.
Published on in JavaScript and Regular expressions
Last updated on
How to convert
'/foo/bar/baz/'
into an array of
'/'
, '/foo/'
, '/foo/bar/'
, and '/foo/bar/baz/'
.
Example use case: building breadcrumb navigations.
Published on in Miscellaneous
Last updated on
Expiring skills vs permanent skills and just-in-time learning vs just-in-case learning.
new Date()
and Date.parse()
are bad at parsing datesPublished on in JavaScript
Last updated on
Use them only with certain date time formats, and use a library for parsing fancy formats.
Published on in JavaScript
Last updated on
The error is thrown when calling a function
whose this
keyword isn't referring to the object where it originally did,
i.e. when the "context" of the function is lost.
Published on in Pug
Last updated on
Use string interpolation at the beginning of a line,
e.g. #{myVariable}
.
array.shift()
vs array.unshift()
in JavaScriptPublished on in JavaScript and Mnemonics
Last updated on
shift()
removes the first array item,
and unshift()
prepends items to the array.
But how to remember which is which?
toLocaleString()
in Node.jsPublished on in JavaScript and Node.js
Last updated on
With Node.js 13+,
it should just work.
With earlier Node.js versions,
you need to install and use the full-icu
package.
Published on in Battlestation
Last updated on
Much better than a Jabra headset, but also much pricier. Why a dynamic XLR microphone instead of a condenser USB microphone? Read on to find out.
Published on in Clean code, CSS and JavaScript
Last updated on
These two similar principles state that the behavior of code should be obvious on inspection and that code should be located where it's relevant.
Published on in JavaScript
JavaScript doesn't provide a native way to get the week number of a date. Just use a library instead.
Published on in JavaScript and Regular expressions
Last updated on
E.g. how to capture overlapping pairs of letters from the string 'abcde'
,
i.e. 'ab'
, 'bc'
, 'cd'
and 'de'
.
Spoiler: with lookahead and lookbehind assertions.
fn.apply()
vs fn.call()
in JavaScript + better alternativePublished on in JavaScript and Mnemonics
Last updated on
Mnemonic:
"a" (apply()
) for an array,
"c" (call()
) for commas.
But Reflect.apply()
is better.
xmlns
and version
SVG attributesPublished on in SVG
Last updated on
The xmlns
attribute is required for SVG files
but optional for inlined SVGs.
The version
attribute is always optional.
Published on in JavaScript and React
Last updated on
If you need form input values only at the time of form submission, uncontrolled inputs can be nice to work with.
Published on in JavaScript
Last updated on
My quick notes on a funny but informative video (11:27) that explains how tail call optimization (TCO) works. Bonus: does JS support TCO? Spoiler: yes but no.
package.json
automaticallyPublished on in JavaScript
Last updated on
Just run npx sort-package-json
.
Published on in Git
Last updated on
Never run git push --force
.
Instead run git push --force-with-lease
or alias it to git please
.
Published on in Git
Last updated on
Run git reset HEAD~
or alias it to git undo
.
Bonus: how to use the commit message from the undoed commit.
Published on in JavaScript
Last updated on
A simple reducer to chunk (split) an array into smaller arrays.
Published on in C#, Episerver and JavaScript
Requests with the Accept
header set to application/json
are automatically routed to Content Delivery API.
Here's how to bypass it
and make the request go to a page controller instead.
Published on in English
And RTFA/RTFM stands for "Read The Fine Article/Manual." Who likes profanity, anyway?
Published on in Miscellaneous
Last updated on
RFC 2119 defines key words such as "MUST," "MUST NOT," "REQUIRED" and "SHALL" that are often used in specifications. Here's a summary of the key word definitions.
Published on in JavaScript, Mithril.js and React
Last updated on
JSX is just JS under the hood.
Hyperscript is like that JS,
but better.
Example:
h('a.link', { href }, 'Click me')
is nicer than
<a className="link" href={href}>Click me</a>
,
right? Right?!
contenteditable
+ ::first-letter
+ Chrome = buggy comboPublished on in CSS
Last updated on
This combination causes weird behavior and data loss
because of a bug in Chrome,
so it's best not to use contenteditable
and ::first-letter
together.
When migrating content from another platform to Episerver,
I wanted to set a specific datetime for each content's Modified date (Saved
property).
Sounds simple,
but it was only possible by using Episerver's internal, undocumented API.
default
doesn't have to be the last casePublished on in C#, Clean code, JavaScript and TypeScript
Last updated on
Non-last default
cases are confusing
but perfectly valid.
Sometimes it makes sense to place them at the beginning or in the middle.
Was it [text](url)
or (text)[url]
?
Use this one weird trick to remember –
Markdown consultants HATE it!
Spoiler: it's the former since it looks like a function call.