Programming, Language: Javascript

All posts

Recent posts

Genuary 2026.03: Fibonacci forever

3) Fibonacci forever

Fibonacci

This is entirely based around this Fibonacci generator function:

function makeFibber(maxValue = 1000) {
  let a = 1;
  let b = 1;
  return () => {
    let n = a + b;
    a = b;
    b = n;
    if (b > maxValue) {
      a = 1;
      b = 1;
    }
    return a;
  };
}

Make a fibber and then just keep calling it for next values.

All sorts of exciting options here!

read more...


Locking BGA tabs with UserScripts

I play a lot of games on Board Game Arena (BGA!). A lot of those are turn based games with random people, but I have two subsets of games that I consider ‘more important’:

  • Turn based games with people I know
  • Alpha games I’m testing

Unfortunately, the first tends to have longer ‘per turn’ times and the latter doesn’t have a timer at all, so both end up right at the very end of the sorted table list. But both, I’d rather play first and in-between other games.

Super niche problems, I know.

Generally, my solution has been to keep a tab open for each of those games in a Firefox Tab Group, but in those cases, I keep navigating off those pages accidentally (thank you next table button).

Super super niche problems, now.

In any case, I whipped up a quick userscript (I use ViolentMonkey) that will:

  • Detect if a tab I’m on is one of the games I want to ’lock’
  • Remove the next table button (buttons; there are two different ones)
  • Disable navigation (at least make it pop up a warning)
  • Periodically refresh the tab (BGA tends to go to sleep in the background)

read more...


Parsing PEM Certificates & ASN.1 in Javascript

I recently had a conversation about parsing HTTPS/TLS/etc certificates client side (so that various values could be compared). There are, of course, libraries for that, but where’s the fun in that? Let’s dig in ourselves!

I thought of course it would be a well specified format and it wouldn’t take more than a few minutes to parse… right?

Right?

read more...


WebCrypto SHA-256 HMAC

A quick random thing I learned that I found helpful (and you might too!):

async function hmac(text, secret) {
    let enc = new TextEncoder("utf-8");
    let algorithm = { name: "HMAC", hash: "SHA-256" };
    
    let key = await crypto.subtle.importKey("raw", enc.encode(secret), algorithm, false, ["sign", "verify"]);
    let signature = await crypto.subtle.sign(algorithm.name, key, enc.encode(text));
    let digest = btoa(String.fromCharCode(...new Uint8Array(signature)));

    return digest;
}

This is a function that uses the Web Crypto API to calculate a SHA-256 HMAC of a string given a secret value.

I mostly worked this out so that I could figure out how exactly TextEncoder worked, along with importKey (to turn a secret into proper key material) and also how to convert that back into a hex digest.

>> await hmac("lorem ipsum", "super secret")
"qArFX93Zi83ccIayhYnuFDpd4pk3eB4rZYDvNteobSU="

>> await hmac("lorem ipsum doler sit amet", "super secret")
"klTAioH5nNkguNhU2YcJshaZZtJW9DEb+MTqz4NWq8E="

>> await hmac("lorem ipsum", "even more super secret!")
"RoQLg2uz5KWLMJM72VExH5gZOls5bdZZyzHi678eDWs=" 

>> await hmac("lorem ipsum", "super secret")
"qArFX93Zi83ccIayhYnuFDpd4pk3eB4rZYDvNteobSU="

Disclaimer: This totally counts as rolling your own crypto. Don’t do this unless you know what you’re doing. 😄

Disclaimer disclaimer: I only rarely know what I’m doing. 😄 😄

Also, for what it’s worth, this is equivalent to the Python standard libraries’ hmac + base64 :

>>> base64.b64encode(hmac.digest(b'super secret', b'lorem ipsum', 'SHA256')).decode()
'qArFX93Zi83ccIayhYnuFDpd4pk3eB4rZYDvNteobSU='

Genuary 2023.31: Break a previous image

Genuary!

Spend a month making one beautiful thing per day, given a bunch of prompts. A month late, but as they say, ’the second best time is now'.

Let’s do it!

31) Deliberately break one of your previous images, take one of your previous works and ruin it. Alternatively, remix one of your previous works.

read more...


Genuary 2023.30: Minimalism

Genuary!

Spend a month making one beautiful thing per day, given a bunch of prompts. A month late, but as they say, ’the second best time is now'.

Let’s do it!

30) Minimalism


let gui;
let params = {
  lineWidth: 10,
  minWidth: 50,
  maxWidth: 100, maxWidthMax: 400,
  minHeight: 50,
  maxHeight: 100, maxHeightMax: 400,
  colorChance: 0.1, colorChanceMin: 0, colorChanceMax: 1, colorChanceStep: 0.01,
}

let box;
let colors = [
  "red",
  "blue",
  "yellow",
]

function setup() {
  createCanvas(400, 400);
  
  box = {
    x: -params.lineWidth,
    y: -params.lineWidth,
    width: random(params.minWidth, params.maxWidth),
    height: random(params.minHeight, params.maxHeight),
  }

  gui = createGuiPanel('params');
  gui.addObject(params);
  gui.setPosition(420, 0);
}

function draw() {
  strokeWeight(params.lineWidth);
  stroke("black");
  
  if (random() < params.colorChance) {
    fill(random(colors));
  } else {
    fill("white");
  }
  
  rect(box.x, box.y, box.width, box.height);
  
  box.y += box.height;
  box.height = random(params.minHeight, params.maxHeight);
  
  if (box.y > height) {
    box.x += box.width;
    box.y = -params.lineWidth;
    box.width = random(params.minWidth, params.maxWidth);
    box.height = random(params.minHeight, params.maxHeight);
  }
  
  if (box.x > width) {
    noLoop();
  }
}

I did have a sketch before that that ended up getting a little un-minimal:

read more...