Skip to content

Instantly share code, notes, and snippets.

View jed's full-sized avatar

Jed Schmidt jed

View GitHub Profile
@jed
jed / jsx-runtime.js
Created September 23, 2024 01:06
minimum viable JSX-to-DOM implementation
export let Fragment = () => document.createDocumentFragment();
export let jsx = (node, { children = [], ...props }) =>
jsxs(node, { ...props, children });
export let jsxs = (node, { children, ...props }) => {
node =
typeof node === "function" ? node(props) : document.createElement(node);
for (let name in props) {
@jed
jed / mimedb.js
Last active October 6, 2023 02:56
Using the OPFS API to determine which mime type a browser infers based on file extension.
/*
This script runs a Deno server that serves an html page that
uses the the Origin Private File System API to determine which
mime type a browser infers based on file extension. It uses
the mime-db database to enumerate all candidate extensions.
For background, see https://mastodon.social/@jed/110533898437100502
1. Run deno run -A --watch mimedb.js
@jed
jed / README.md
Last active November 19, 2022 20:03
Making your Mastodon account discoverable from your domain, using Cloudflare page rules

Making your Mastodon account discoverable from your own domain, using Cloudflare page rules

Are you (1) moving to Mastodon, but (2) want to use your own Cloudflare-hosted domain for discoverability, and (3) don't want the hassle of managing your own instance?

Well, here's a quick way to make sure that folks can find you when they search Mastodon with your domain. The UX is like this:

image

(If you're not on Cloudflare or would rather just host a file, use Maarten Balliauw's post, How to discover Mastodon account via custom domain, from which this technique was inspired.)

@jed
jed / resolve_tco.js
Last active April 30, 2024 01:33
t.co resolver for twitter archives
// this script replaces all t.co links in the data/tweets.js file of an unzipped twitter archive with their resolved urls.
// it replaces all text inline, so be sure to make a backup of the file before running.
// usage: deno run -A resolve_tco.js {path to data/tweets.js}
let file = Deno.args[0]
let text = await Deno.readTextFile(file)
let matches = text.match(/"https:\/\/t\.co\/\w+"/g)
let unique = [...new Set(matches)]
console.log('%s urls found.', unique.length)
if (unique.length) for (let match of matches) {
// per https://twitter.com/yoshuawuyts/status/1494119486429007879
// "In JavaScript, is there a function which takes N Promises, and returns an asyncIterator which yields N resolved values?"
let promises = Array.from({length: 10}, (n, i) => {
return new Promise(cb => setTimeout(cb, Math.random() * 1e3, i))
})
let iterator = iteratePromises(promises)
for await (let value of iterator) console.log(value)
export default (build, namespace = 'view-source') => ({
name: namespace,
setup({initialOptions, onLoad, onResolve}) {
let options = {...initialOptions, write: false}
let filter = new RegExp(`^${namespace}:`)
onResolve({filter}, ({path, importer}) => {
path = path.replace(filter, '')
try { importer = new URL(importer) }
catch (e) { importer = new URL(`${namespace}://${importer}`) }
@jed
jed / tee.js
Last active November 24, 2020 17:59
Teeing an asynchronous iterator
function tee(asyncIterable) {
let source = asyncIterable[Symbol.asyncIterator]()
return [[], []].map((buffer, i, buffers) => ({
async next() {
if (0 in buffer) return buffer.shift()
let item = await source.next()
if (!item.done) buffers[1 - i].push(item)
@jed
jed / iterator.js
Last active January 21, 2021 01:56
Turning callbacks into async iterators, with a React hook-like API.
// Example usage:
//
// void async function() {
// let [clicks, onclick] = iterator()
// document.querySelector('button').addEventListener('click', onclick)
// for await (let click of clicks) console.log(click)
// }()
export default function iterator() {
let done = false
@jed
jed / s3-etag.js
Last active March 5, 2018 13:36
Create an etag for an S3 object. Assumes object is uploaded with exact chunk size.
const {createReadStream} = require('fs')
const {createHash} = require('crypto')
module.exports = (path, chunkSize = 5242880) => {
return new Promise((resolve, reject) => {
const hashes = []
const options = {highWaterMark: chunkSize}
const rs = createReadStream(path, options)
rs.on('error', reject)
@jed
jed / deploy.sh
Last active April 24, 2024 15:45
Using AWS CloudFormation to deploy an edge lambda
#!/bin/sh
aws cloudformation deploy \
--template-file stack.yaml \
--stack-name edge-lambda-test \
--capabilities CAPABILITY_IAM \
--parameter-overrides Nonce=$RANDOM