Skip to content

Instantly share code, notes, and snippets.

View barneycarroll's full-sized avatar
🛠️
Working on Mithril type stuff

Barney Carroll barneycarroll

🛠️
Working on Mithril type stuff
View GitHub Profile
// Serialise command-line parameters of form:
// `--boolean`, `--key=value`, `--multiple:value1 --multiple:value2`
export default args => args.reduce((input, arg) => {
const [param, key, verb, value] = (/--(\w+)(=|:)?(.+)?/).exec(arg) || []
if (param)
input[key] = (
// No verb means boolean; '=' means direct assignment; ':' means accumulate array
!verb ? true : verb == "=" ? value : !input[key] ? [value] : [...input[key], value]
)
@barneycarroll
barneycarroll / cor.js
Created October 26, 2021 08:14
Generators as generic sub-routines
‎‎​
@barneycarroll
barneycarroll / changeTag.js
Created August 3, 2021 12:12
Replace an element with a new one that has a different tagName
export default function changeTag(original, tagName){
// Create a replacement tag of the desired type
const replacement = document.createElement(tagName)
// Grab all of the original's attributes, and pass them to the replacement
Array.prototype.forEach.call(original.attributes, ({name, value}) => {
replacement.setAttribute(name, value)
})
// Persist contents
@barneycarroll
barneycarroll / ui_io.js
Created May 23, 2021 20:57
User Interface Input / Output is a tool for observing all event triggers (UI input) & DOM mutations (UI output). Initialised with an optional callback function which receives all such entries in format {type: 'mutation' || 'event', time: performance.now(), data: originalEventOrMutationRecords}, the returned instance exposes {logs, next, disconne…
import muty from 'muty'
export default function ui_io(callback = Function.prototype){
const {addEventListener} = EventTarget.prototype
const promises = []
const listeners = []
const logs = []
function register(entry){
@barneycarroll
barneycarroll / eventListenerListener.js
Created May 12, 2021 11:39
Intercept & release / remove all event listeners. Partially as an easy way to make Mithril router single-SPA compliant.
const {addEventListener} = EventTarget.prototype
export default function EventListenerListener({
blocking = false,
removing = true,
visitor = Function.prototype,
} = {}){
if(this instanceof EventListenerListener){}
else return new EventListenerListener(...arguments)
const muties = new Set
class Muty extends MutationObserver {
observe(){
muties.add(this)
super.observe(...arguments)
}
disconnect(){
@barneycarroll
barneycarroll / .js
Last active June 29, 2022 15:07
Simple CSS-in-JS via speculative 'MFX' idiom. MFX inverts the typical convenience component interface for Mithril: 1) no opportunity to return virtual DOM; 2) completely flexible input signature; 3) executes on every render; 4) returns a lifecycle dictionary. The mechanism is a very simple wrapper for a lifecycled fragment which always produces …
import css from './css.js'
let color = 'red'
let fontFamily = 'sans-serif'
m.mount(document.body, {
view: () => [
m('p',
css`
color: ${ color };
@barneycarroll
barneycarroll / mithril.steps.js
Created March 26, 2021 15:26
What if we could yield & await as discrete mechanisms for stepping through lifecycle?
// Async generators don't actually work this way: all yields implictly mandate asynchronous (non-synchronously-blocking) resolution under the hood; so in practice it's probably better to be honest and make this unambiguously wasteful & imprecise and have all steps as explicit awaits. 🙄
const KitchenSink = steps(async function * ($){
$.view(v =>
m('p.counter', $.attrs.value, '!')
)
yield $.create
style({
transition : 'none',
@barneycarroll
barneycarroll / life-cycle.js
Last active March 14, 2021 13:16
A generic lifecycle custom element for use in frameworks that don't implement lifecycle
customElements.define('life-cycle', class LifeCycle extends HTMLElement {
constructor(){
super()
}
connected(){}
connectedCallback(){
this.style.display = 'contents'
this.connected(...arguments)