See release 10.0.0-alpha.0 for a full list.
h
->createElement
VNode.nodeName
->VNode.type
VNode.attributes
->VNode.props
VNode.children
->VNode.props.children
##### | |
# File: send-eml.sh | |
# Author: pl12133 | |
# Description: Send an eml file through an SMTP service using netcat | |
# Usage: ./send-eml.sh [file] [smtp-server] | |
##### | |
set -e | |
# like `cat`, but it waits for a reply. | |
function slowcat(){ cat "$@" | while read; do sleep 0.5; echo "$REPLY"; done; } |
See release 10.0.0-alpha.0 for a full list.
h
-> createElement
VNode.nodeName
-> VNode.type
VNode.attributes
-> VNode.props
VNode.children
-> VNode.props.children
function leakyDebounce(fn, delay, max = 1) { | |
let timer, ctx, args, outstanding = 0, queue = []; | |
function done() { | |
[ ctx, args ] = queue.shift(); | |
fn.apply(ctx, args); | |
if (queue.length) { | |
timer = setTimeout(done, delay); | |
} | |
} |
function breakOnUrlMatch(str, callback) { | |
let nextOpen = XMLHttpRequest.prototype.open; | |
XMLHttpRequest.prototype.open = function monkeypatchedOpen(...args) { | |
let url = args[1]; | |
if (url && url.indexOf(str) >= 0) { if (callback()) { return; } } | |
// console.log('XHR for ', url); | |
return nextOpen(...args); | |
} | |
let nextFetch = window.fetch; |
import { h } from 'preact'; | |
function lastChild(arr) { | |
return arr && arr.length ? arr[arr.length - 1] : undefined; | |
} | |
function get(obj, key, def, p) { | |
p = 0; | |
key = key.split ? key.split('.') : key; | |
while (obj && p<key.length) obj = obj[key[p++]]; |
// This is mostly working but also useless, because the audio volume will periodically be reset during the discussion. | |
window.__hangoutsVolumeBookmarkletCleanup = (function createAudioModMenu(window, undefined) { | |
if (window.__hangoutsVolumeBookmarkletCleanup) { | |
window.__hangoutsVolumeBookmarkletCleanup(); | |
} | |
var document = window.document; | |
var participants = Array.from(document.querySelector('[aria-label="Video call participants"]').childNodes).slice(0, -1); | |
var audios = Array.from(document.querySelectorAll('audio')).reverse(); | |
var children = []; |
function isInert(node) { | |
// See https://www.w3.org/TR/html5/editing.html#inert | |
let sty = getComputedStyle(node); | |
return node.offsetHeight <= 0 || /hidden/.test(sty.getPropertyValue('visibility')); | |
} | |
function focusNext(e) { | |
// Selector lifted from `jkup/focusable.git` | |
let focusable = Array.from(document.querySelectorAll('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex="0"], [contenteditable], audio[controls], video[controls]')), | |
step = e && e.shiftKey ? -1 : 1, | |
activeIndex = focusable.indexOf(document.activeElement), |
var vConsoleHid = (function hookVirtualConsole(window, document, undefined) { | |
var [ input, btn, container, log ] = [ 'input', 'button', 'div', 'div' ].map((tag) => document.createElement(tag)); | |
container.setAttribute('style', | |
`position: fixed; z-index: 99999999; left: 10vw; width: 80vw; top: calc(80vh - 100px); height: 160px; border: 2px solid #ccc; background-color: rgba(0,0,0,.2); overflow-y: auto;` | |
); | |
input.setAttribute('style', 'width: 95%; position: absolute; bottom: 0; left: 0;' ); | |
input.setAttribute('placeholder', 'JavaScript' ); | |
btn.textContent = 'Eval'; | |
btn.setAttribute('style', 'width: 5%; position: absolute; bottom: 0; right: 0;' ); | |
function submitScript() { |