Skip to content

Instantly share code, notes, and snippets.

@AstraLuma
Last active September 18, 2025 05:35
Show Gist options
  • Select an option

  • Save AstraLuma/c8e37d0dd38cd378627d62d30684c4ef to your computer and use it in GitHub Desktop.

Select an option

Save AstraLuma/c8e37d0dd38cd378627d62d30684c4ef to your computer and use it in GitHub Desktop.
/*
`\\ \\ !||
\ \\\\\\\\, !||
\,,.\\\,\ ,\ |\\/!||
\\V\ ,\ V \\| |//!||
\\VVVV\\\V/ |/ //||
VVVV\\((-\\./ /||
\VVV_\\==- ''/|FF|
\V( \ ., ,|JL|
\_\| (( \||/
. | / ,|| \
__;__ `. `--' ( LJ )\
[""""""""`._/ |) /".)
)`` """'-"")( "./
_,-,-"'-.__ __,--;""-,-,_ (
_.-"( ( "" / ( "._
/ | |o( /o/ ,""
( | '-" \/ /( )
|\ : / (
[" \ ". _ |
`--.\ "." ""
/_ : \ //.
[==--,\ ,-. ,-. ) ;
/ ``/`\ \O \ ,-. / O/ / ;
: | : \ \." | ",/ / ; ;
[====] \ ,\ \ |("`_,/. /. ;
} "/ \/ ) (__{/ \____\/ \ ;
"__ | \_,_ / O/ "-.\__/
,' `. __| /" !,\______,'_
: ;] ( ,--' _" `. "_,".
;--'( / / _,' ; `. / (
[===]' _;-' ,' | `. \ ( |.
' ; .' o_,' | \ o `.__|_.';
: ; \o,' | `._ o o /
[ctr] \( | `-----/
[===] ; \ | |
; \ | \ | |
) ,\ ; | | :
| /(( | | : |
\\ ;_, | | | |
``---` ; | | :
;' | : `:
| ; `: |
| : ; __|_|
; :;' [o_|o/
;' : :: ` :``:
| : : : |
; .: \ : `: |
| .: ; `;. : : |
| : ; : : : |
| : ; | | : '.
; : ,; | :. : :
;' : ; : : '. '.
| | \ : \ :
/| ; `\ | || |
; | | `| :. || |
| : | | | || |
| | | | : ||.'.
; ; ; ; : ':| |
/ / | ___ | : || :
;' | ;"-"!!8"",; : || |
| /| \ !,##/!8!/, | || |
|/#'._ )!#[]#!88\| : || \
\| `-,-' !#==#!88|` :,-.__||,-'
` ,####.""""7"",---'
#====# ;___ (,_._
###### [_____/o/==._
`#==#' \ ""__ __)
`##' |####|-######
stampede.js - The sequel to the sixty billion double-dollar JavaScript library.
This is htm+DOM, plus a few utilities. It's meant to be used with custom
elements and other vanilla browser features.
import $$ from 'stampede.js';
*/
"use strict";
import htm from "https://unpkg.com/htm/mini/index.module.js"; // FIXME: Inline this
/**
* A ref for use with dom``
*
* If dom`` encounters a Ref outside of #ref, it'll dereference it.
*/
export class Ref {
#value;
get() {
return this.#value;
}
set(value) {
this.#value = value;
}
/// The ID of the stored element, if there is one
get id {
if (this.#value instanceof Element) {
return this.#value.id;
}
}
}
/**
* Generate a unique ID.
*
* Each invocation is guarenteed to generate a unique string.
*/
if (crypto.randomUUID != undefined) {
export function id() {
return crypto.randomUUID();
}
} else {
// randomUUID is only available in secure contexts, so have a fallback
let id_sequence = 0;
export function id() {
return `id${id_sequence++}`;
}
}
const raw_htm = htm.bind((tagName, attributes = {}, ...children) => {
// Implement this if we want <${func} /> to work
// if (typeof tagName === "function") return tagName();
// Create the element
const e = document.createElement(tagName, { is: (attributes || {}).is });
// Process attributes
for (const k of Object.keys(attributes || {})) {
const rawval = attributes[k];
let val = rawval;
if (rawval instanceof Ref) {
val = val.get();
}
// JS Props
if (k.startsWith(".")) {
e[k.substr(1)] = val;
// Events
} else if (k.startsWith(":")) {
e.addEventListener(k.substr(1), val);
// Special attr #ref
} else if (k == "#ref") {
rawval.set(e);
// Special attr #id
} else if (k == "#id") {
e.setAttribute("id", id());
// Reserved for other special attrs
} else if (k.startsWith("#")) {
throw `Unknown special attribute ${k}`;
// Regular node attributes
} else {
e.setAttribute(k, val);
}
}
// Flatten children (we can receive an array of array)
children = children.reduce(function (acc, child) {
return Array.isArray(child) ? [...acc, ...child] : [...acc, child];
}, []);
// Append children to the element
for (const child of children) {
if (typeof child === "string" || typeof child === "number") {
e.appendChild(document.createTextNode(child));
} else if (child instanceof Node) {
e.appendChild(child);
} else {
throw `Cannot add ${child} as child of ${e}`;
}
}
return e;
});
/**
* Tagged template that generates a DOM tree using JSX-like syntax.
*
* JSX is extended by allowing some special property names:
* - <tag .prop={}> will set the JavaScript property
* - <tag :event={}> will add a handler to an event (similar to onevent)
* - <tag #ref={}> will store a reference to the node for later use
* - <tag #id> will generate an ID
* - <tag attr={}> will set the node attribute as normal
*
* This is implemented using https://github.com/developit/htm
*/
export function dom(strings, ...values) {
const elems = raw_htm(strings, ...values);
if (elems instanceof Array) {
const frag = document.createDocumentFragment();
for (const e of elems) {
frag.appendChild(e);
}
return frag;
} else if (elems instanceof Node) {
return elems;
} else if (typeof elems !== "object") {
// Strings, numbers, etc
return document.createTextNode(elems);
} else {
throw `Value ${elems} not convertable to a DOM object`;
}
}
/// Promise that resolves when DOMContentLoaded happens
export const ready = new Promise((resolve, reject) => {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", () => resolve());
} else {
resolve();
}
});
// The original doubledollar.js included a bunch of promise and misc utilities I
// might copy over in the future; we'll see what's useful.
export default {
dom: dom,
ready: ready,
Ref: Ref,
id: id,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment