Skip to content

Instantly share code, notes, and snippets.

// ==UserScript==
// @name YouTube Link Title
// @description Adds video titles, shows previews and embeds on click. Also supported: Vimeo, LiveLeak, Dailymotion, vidme, WorldStarHipHop, Vine, Coub, Streamable
// @namespace http://w9p.co/userscripts/
// @version 2017.2.28
// @author kuehlschrank
// @homepage http://w9p.co/userscripts/ytlt
// @icon https://w9p.co/userscripts/ytlt/icon.png
// @include http*
// @exclude http*//*.google.*/*
const arrayMarker = Symbol("sql.array");
export interface ArraySqlReplacement {
[arrayMarker]: true;
array: any[];
joiner: string;
}
const isArraySqlReplacement = (value: any): value is ArraySqlReplacement =>
typeof value === "object" && value !== null && value[arrayMarker];
export function* range(start, endExclusive, step) {
switch (arguments.length) {
case 1:
endExclusive = start;
start = 0;
case 2:
step = start > endExclusive ? -1 : 1;
}
if (start === endExclusive) {
export type AtLeastOne<T> = [T, ...T[]];
export function groupByUsing<V, K extends keyof V, U>(
iterable: Iterable<V>,
key: K | ((value: V, index: number) => V[K]),
callback: (value: V, index: number) => U,
): Map<V[K], AtLeastOne<U>> {
const mapper = typeof key !== "function" ? (v: V) => v[key] : key;
const map = new Map<V[K], AtLeastOne<U>>();
function drop(iterator, amount) {
for (let i = 0; !(i >= amount); ++i) {
if (iterator.next().done) {
break;
}
}
return iterator;
}
'use strict';
function onLoad() {
cfg.load();
const prefix = 'div.' + webm.getStyle('cozyMessage') + ' ';
const q = Object.values(sites).flatMap(({ patterns: p }) => p.map(x => 'a[href*="' + x +'"]'));
q.push('a[href*="//t.co/"]');
links.query = prefix + q.join(',' + prefix);
links.process(d.body);
new MutationObserver(onMutations).observe(d.body, {childList:true, subtree:true});
function once(fn) {
const { name, length } = fn;
let called = false;
// match .name of argument
const wrapped = {
[name]() {
if (!called) {
called = true;
fn.apply(this, arguments);
export const groupByUsing = (iterable, key, callback) => {
const mapper = typeof key !== "function" ? x => x[key] : key;
const map = new Map();
let i = -1;
for (const value of iterable) {
const mappedKey = mapper(value, ++i, key);
const mappedValue = callback(value, i, key);
const group = map.get(mappedKey);
/* use sleep from below, or bring your own */
// export const sleep = millis => new Promise(_ => setTimeout(_, millis));
async function impl(sentinel, func, interval, args) {
for (; !sentinel.aborted; await sleep(interval)) {
await func(...args);
}
}
export default function runAtIntervals(func, interval, ...args) {
export const IndexableMap = class extends Map {
constructor(iterable) {
super();
this._values = [];
if (iterable != null) {
for (const [key, value] of iterable) {
this.set(key, value);
}
}
}