Skip to content

Instantly share code, notes, and snippets.

View jamesknelson's full-sized avatar

James K Nelson jamesknelson

View GitHub Profile
@jamesknelson
jamesknelson / index.html
Created March 27, 2020 14:37
JavaScript Fireworks
<body>
<style>
body {
background-color: black;
overflow: hidden;
}
.firework {
top: 0;
left: 0;
@jamesknelson
jamesknelson / index.html
Created March 25, 2020 14:41
Falling sakura 1
<body>
<style>
body {
/* background-color: rgb(195, 226, 224); */
background-color: black;
overflow: hidden;
}
.petal {
position: absolute;
@jamesknelson
jamesknelson / index.html
Last active March 24, 2020 14:30
Fireworks with HTML/CSS
<style>
body {
background-color: black;
}
.dot {
position: absolute;
top: 50%;
left: 50%;
}
@jamesknelson
jamesknelson / index.html
Created March 21, 2020 14:35
WIP code for first lesson of Learn Something About Programming In 30 Minutes
<link href="https://fonts.googleapis.com/css?family=Squada+One&display=swap" rel="stylesheet">
<style>
body {
background-color: black;
}
h1 {
color: #EEE;
font-family: 'Squada One', cursive;
font-size: 60px;
@jamesknelson
jamesknelson / model.js
Created November 24, 2019 04:26
A model class for storing data fetched with React Suspense
const PurgeDelay = 1000
class Model {
fetcher: (id: string) => Promise<any>
cache = {}
callbacks = {}
holds = {}
purgeTimeouts = {}
@jamesknelson
jamesknelson / createSubscribe.js
Created October 22, 2019 07:41
Turn an async function into something you can subscribe to (untested)
const requests = {}
export const createSubscribe = (asyncFn) => {
return subscribeToData = (params, onUpdate) => {
onUpdate('pending')
const key = JSON.stringify(params)
const request = requests[key]
if (!request) {
request = requests[key] = {
@jamesknelson
jamesknelson / README.md
Last active August 20, 2022 22:21
Convert a video into a gif

A 4-line shell script to convert your movies into gifs. Defaults to 10fps, 700px wide.

WIDTH=420 FPS=12 togif input.mov

You'll need to have ffmpeg installed -- on mac, you can do this with brew:

brew install ffmpeg
const CombinedStream = require('combined-stream2');
function concatStringsAndStreams(strings, ...args) {
let combinedStream = CombinedStream.create()
combinedStream.append(Buffer.from(strings[0], 'utf8'))
for (let i = 0; i < args.length; i++) {
let arg = args[i]
let string = strings[i+1]
if (arg && arg.pipe) {
combinedStream.append(arg)

mapObservableToChunkIterator(observable, mapValueToChunks, mapErrorToChunks?): Generator<Promise | Chunk[]>

A function that accepts an Observable with a subscribe() method, and optionally with a getCurrentValue() or getCurrentResult() method.

It returns a Generator that yields Promise (when waiting for a new value) or Chunk objects (i.e. objects that extend { type: string }).

By default, mapErrorToChunks takes the error emitted by an observable, and yields [{ type: 'error', error: error }].

When the observable is complete, the Generator's next() function will return { done: true }.

@jamesknelson
jamesknelson / component-routing.js
Last active March 19, 2019 11:22
Two APIs for routing with React that support POST methods and SSR.
/**
UPDATE:
This component and hook based routing/fetching API won't work, as `useAsync()`
is an impossible component.
In order to use async functions to respond to route changes, the functions will
need to be registered with a parent cache/provider with a unique key. As such, a
more natural component-based architecture would involve a `<Route path>` component