Skip to content

Instantly share code, notes, and snippets.

View samthor's full-sized avatar

Sam Thorogood samthor

View GitHub Profile
#!/usr/bin/env python3
"""Returns the number of members of a master group in other groups.
Accepts Google Groups member export CSVs. Usage:
./members.py < master.csv other.csv groups.csv
"""
import csv
import sys
@samthor
samthor / shadowlisten.js
Last active May 18, 2020 18:55
Listener to provide up-to-date Shadow DOM focus events
/**
* Copyright 2017 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
if ('serviceWorker' in navigator) {
// sw.js can literally be empty, but must exist
navigator.serviceWorker.register('/sw.js');
}
@samthor
samthor / manifest.json
Last active August 14, 2021 18:55
simple manifest.json
{
"name": "Your Great Site",
"short_name": "Site 😎",
"description": "Learn how to create and share something or other.",
"start_url": "/?homescreen=1",
"background_color": "#000000",
"theme_color": "#0f4a73",
"icons": [{
"src": "icon-256.png",
"sizes": "256x256",
@samthor
samthor / gulpfile.js
Last active October 17, 2016 08:47
Polymer/Closure: Step #2, Compile
const closure = require('google-closure-compiler-js').gulp();
const fs = require('fs');
gulp.task('compile', ['merge'], function() {
// nb. This is a bit awkward, but we need to load the Polymer externs so that
// Closure can compile Polymer code correctly.
const externsPath =
'node_modules/google-closure-compiler-js/contrib/externs/polymer-1.0.js';
const externsSrc = fs.readFileSync(externsPath, 'utf-8');
@samthor
samthor / gulpfile.js
Last active October 17, 2016 09:37
Polymer/Closure: Step #1, Merge and split
const gulp = require('gulp');
const vulcanize = require('gulp-vulcanize');
const crisper = require('gulp-crisper');
gulp.task('merge', function() {
return gulp.src('src/elements.html')
.pipe(vulcanize({
excludes: ['bower_components/polymer/polymer.html'], // polymer doesn't compile properly
}))
.pipe(crisper({onlySplit: true})) // don't inline script, since we compile it again
@samthor
samthor / script.js
Created August 1, 2016 00:25
Shadow DOM v1 polyfill experiment 🔧
(function() {
if (Element.prototype['attachShadow']) {
return false; // implemented already
}
const supported = ['article', 'aside', 'blockquote', 'body', 'div', 'footer', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'nav', 'p', 'section', 'span'];
/**
* Implements all the fake methods on Element.
*/
@samthor
samthor / gulpfile.js
Created July 21, 2016 02:15
Gulpfile that compiles with Babel
/*
* Copyright 2016 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
@samthor
samthor / gulpfile.js
Created July 21, 2016 01:53
Minimal gulpfile for building JS
/*
* Copyright 2016 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
@samthor
samthor / counterdict.py
Created June 15, 2015 07:41
python counter helper
#!/usr/bin/env python3
import collections
class counterdict(collections.defaultdict):
def __init__(self):
collections.defaultdict.__init__(self, counterdict)
def __sub__(self, value):
"""Upgrade this counter to a number.