Last active
September 18, 2025 05:35
-
-
Save AstraLuma/c8e37d0dd38cd378627d62d30684c4ef to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| `\\ \\ !|| | |
| \ \\\\\\\\, !|| | |
| \,,.\\\,\ ,\ |\\/!|| | |
| \\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