vite-plugin-prebundle-workers

Vite's basic premise (send down individual ES modules to the browser) works well in most cases but sometimes it really isn't great.

In my case I really wanted to use both importScripts and ES imports in a Web Worker. This works in the built app 1 but it won't work in dev 2. (I had some old code using OpenCV.js that would've been very cumbersome to change to using ES imports exclusively because I'd have to modify OpenCV.js's distribution).

So instead I made a quick Vite plugin so I could just use importScripts and ES imports! Now my web worker is bundled in dev and on prod. Problem solved.

Footnotes

  1. Because all of the ES imports will be compiled away by the bundler and it'll be run as a classic Web Worker.

  2. An ES module loaded by the browser in a Web Worker can't call importScripts. An error is immediately raised.

timcol

Back when I was doing contract work in the late 00s/early 10s I used a little DOS Batch script I made to track my hours. It worked really well and I loved using it!

I recently started doing some Unity work for my friend at Primer Learning and I wanted a similar time tracker. So I made a little utility: timcol! The name is a shortening of "time collection".

Unlike my previous tool, this one can make invoices and even takes screenshots of my screen so that if I forget to stop it manually I can go back through the screenshots and figure out when I stopped working.

Grassy Knight

The YouTuber Skurry wanted to make a speed run of Hollow Knight where they cut every piece of grass in the game as quickly as possible. Since grass will grow back as soon as you leave and re-enter a level, determining whether they've succeeded at the end of the challenge was going to be very hard.

So I made them a little mod that adds some counters to the top left of the screen!

A screenshot of Hollow Knight with the Grassy Knight mod loaded

It was a very fun project and their final video is great.

tbget

The log viewers we use at Khan Academy usually show tracebacks in some kind of escaped format (with newlines replaced with \n, or the whole thing getting embedded into a large JSON object), so quickly formatting tracebacks has become a pastime for me.

Yesterday I got tired of formatting though, so now I have a fancy tool that can turn the most heinously encoded tracebacks into beautifully formatted emeralds.

Heinous:

'{"test_data": "{\\"data\\": \\"$ tools/runtests.py \\\\nRUNNING ALL SORTS OF TESTS\\\\nSTUFF IS PASSING!!\\\\n^CTraceback (most recent call last):\\\\n File \\\\\\"tools/devshell.py\\\\\\", line 145, in <module>\\\\n from devshell_eval import *\\\\n File \\ \\\\"webapp/tools/devshell_eval.p y\\\\\\", line 4, in <module>\\\\n from assessment_items.models import *\\\\n File \\\\\\"khan27/lib/python2.7/sre_parse.p y\\\\\\", line 126, in __len__\\\\n def __len__(self):\\\\nKeyboardInterrupt\\\\n$\\\\n\\", \\"type\\": \\"traceback\\"}", "test_result": "aborted"}'

Beautiful emerald:

Traceback (most recent call last):
File "tools/devshell.py", line 145, in <module>
from devshell_eval import *
File "webapp/tools/devshell_eval.py", line 4, in <module>
from assessment_items.models import *
File "khan27/lib/python2.7/sre_parse.py", line 126, in __len__
def __len__(self):
KeyboardInterrupt\\\\n$\\\\n\\",
\\"type\\": \\"traceback\\"}", "test_result": "aborted"}'

Die Simulator

Ever play D&D, realize you forgot your dice, and decide to write up a script to roll dice for you? Me too! I made it in Python and didn't spend a ton of time adding features, so its understanding of dice-rolling syntax (like 2d10+8) is pretty minimal, but it works great!

A demo of the die simulator

My initial version of this program had an off by one error which prevented me from ever getting a 20 when rolling a d20! I was upset.

Different Logger

I wanted Python's logging library to give me pretty output and highlight the substituted values. So I made a little library that'd make it do all those things! Here's some output:

Various log messages printed by the logger. A log message with a stack trace printed by the logger.

You don't need to do anything special to use it, just use the Python logging library like normal (ex: logging.error("%s foobars received, expected 17", num_foobars)).

superzippy

I want to distribute some command line scripts to instructors using Galah. They're all on Unixy systems so I can trust that they have Python installed but I've had trouble giving them instructions involving pip before.

Interestingly if you say python file.zip Python will try and execute the __main__.py file in the zip archive. And since the ZIP format places all of its metadata at the end of the file, rather than the start, I can even add a #!/usr/bin/env python\n to the archive and the zip file becomes executable like a normal binary!

Doing it by hand isn't too hard, but to make the process even easier I've created superzippy! It handles it all for me.