Skip to content

Instantly share code, notes, and snippets.

View rauschma's full-sized avatar

Axel Rauschmayer rauschma

View GitHub Profile
// Q: Why not an object literal?
// A: Then you have to create separate constants for the symbols:
// https://2ality.com/2025/01/typescript-enum-patterns.html#using-symbols-as-property-values
type PropertyValues<Obj> = Obj[keyof Obj];
function createEnum<C extends new (...args: unknown[]) => unknown>(enumClass: C): Omit<C, 'prototype'> {
return enumClass;
}
const Color = createEnum(class {
type CreateTuple<Len extends number, Acc extends unknown[] = []> =
Acc['length'] extends Len
? Acc
: CreateTuple<Len, [...Acc, true]>;
;
type Length<Tup extends Array<unknown>> =
Tup['length']
;
type Unshift<Tuple extends Array<unknown>, Value> =
@rauschma
rauschma / assert-type.ts
Last active February 1, 2025 12:16
assert-type: API for asserting types
// This code is now an npm package: https://github.com/rauschma/asserttt
// Slightly modified version of: https://github.com/es-shims/RegExp.escape/blob/main/test/tests.js
import test from 'node:test';
import assert from 'node:assert/strict';
import {regExpEscape as escape} from './regexp-escape.mjs';
const forEach = (arrayLike, callback) => Array.prototype.forEach.call(arrayLike, callback);
const inspect = String;
test('strings', function (st) {

Mastodon for people who are new to social media

In this blog post, I try to explain Mastodon to people who are not familiar with social media and/or beginner computer users. I try to be as jargon-free as I can.

Structure of this blog post:

  • Reading section 1 and 2 takes a bit of effort: They explain important background knowledge for Mastodon. But, in my opinion, the effort is worth it because you’ll find it much easier to use Mastodon. Not having this knowledge can prevent even otherwise advanced computer users from enjoying Mastodon.

  • Section 3 is brief and mentions first steps for actually getting started with Mastodon.

javascript:{
const text = getSelection().toString().trim();
if (text.length > 0) {
const urlToHighlight = new URL(location);
urlToHighlight.hash = '#:~:text=' + encodeURIComponent(text);
navigator.clipboard.writeText(urlToHighlight.href)
.catch((error) => {
alert(String(error));
});
}

Stateless RegExp methods

The issues

  • The rules for the flags /g and /y are complicated.
  • Regular expression operations keep state in RegExp objects, via property .lastIndex. That leads to several pitfalls if a RegExp object is used multiple times. It also makes it impossible to freeze instances of RegExp.
  • String.prototype.replace() accepts a callback where accessing named captures is inconvenient (via an object that is passed as the last argument).

The goal

const primaryColumn = document.querySelector('div[data-testid="primaryColumn"]');
document.body.innerHTML = '';
document.body.append(primaryColumn);
// Per-tweet controls
for (const ele of document.querySelectorAll('div[role="group"]')) {
ele.remove();
}
// Reply widget

Work in a post-growth world

Source: “Le travail dans un monde post-croissance (Dominique Méda)” (56-minute video)

  • Currently, the economy and commercialized work dominates our society.
  • Many societies are not based on “commercialized work” and don’t have a word for it.
  • Adam Smith: work enables us to create wealth. We are interested in the latter (not in work itself).
  • During the 18th century, our values changed significantly: from valuing moderation (a traditional christian value) to valuing wealth.
    • The goal became to produce as much as possible – more than we need to fulfill out immediate needs.
  • Work becomes something meaningful: To assert ourselves in the world, we have to work.
// Batch-delete videos from YouTube’s “Watch later” playlist
// Paste the following code into a browser console while the playlist is open
// Code based on: https://gist.github.com/astamicu/eb351ce10451f1a51b71a1287d36880f?permalink_comment_id=4087416#gistcomment-4087416
//
// (Suggestions for improvement welcome. My approach for waiting for the .click() to finish, feels hacky.)
const pause = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async function remove() {
for (let i=0; i < 100; i++) {
document.querySelector('#primary button[aria-label="Action menu"]').click();