Skip to content

Instantly share code, notes, and snippets.

View boutell's full-sized avatar

Tom Boutell boutell

View GitHub Profile
@boutell
boutell / parse-integers.ts
Created December 1, 2021 12:35
Parse out nonempty lines from a file and convert them to integers
import { readFileSync as read } from 'fs';
const input:Array<number> = read('day-1.txt', { encoding: 'utf8' })
.split('\n')
.map(line => line.trim())
.filter(line => line.length > 0)
.map(line => parseInt(line));
@boutell
boutell / index.js
Created February 7, 2021 19:23
Example of an Apostrophe migration
// in lib/modules/pet-owners/index.js
module.exports = {
extend: 'apostrophe-pieces',
name: 'pet-owner',
addFields: [
{
name: 'cat',
label: 'Cat',
type: 'string'
@boutell
boutell / Dockerfile
Created January 14, 2021 15:12
PoC release asset id generation in a dockerfile
FROM node:current
WORKDIR /app
COPY myasset.js /app
RUN echo `date` > identifier
RUN cat identifier
CMD cat identifier
@boutell
boutell / crop-and-overlay-videos.js
Created December 20, 2020 05:41
Crop and overlay videos using ffmpeg, to copy and paste in space rather than time
const exec = require('child_process').execSync;
// I got coordinates using the screenshot picker in quicktime player,
// but those are scaled to my screen, not the real video. Do some
// corrective fakery
const realDimensions = [ 1920, 1080 ];
const fakeWidth = 1680;
const fakeTom = [ 1400, 0, 280, 156 ];
const fakeVideo = [ 0, 100, 1470, 760 ];
const fs = require('fs');
const content = fs.readFileSync('court-docket.txt', 'utf8').split(/\s*\n\s*/);
const data = {};
data.origin = readOrigin();
data.type = readType();
data.docketNumber = readDocketNumber();
data.subtype = readSubtype();
data.case = readCase();
console.log(data);
self.getCollection = function(callback) {
return self.apos.db.collection('aposCache', function(err, collection) {
if (err) {
return callback(err);
}
self.cacheCollection = collection;
return async.series({
keyIndex: function(callback) {
return self.cacheCollection.ensureIndex({ key: 1, cache: 1 }, { unique: true }, callback);
},
{
"body": [
{
"_index": "testaposdocsdefault",
"_type": "aposDoc",
"_id": "cjnyogcfp0001n3uktsbndy6m"
},
{
"type": "apostrophe-global",
"typeESExact": "apostrophe-global",
import ApostropheFieldMixin from '../mixins/ApostropheFieldMixin.js';
export default {
mixins: [ ApostropheFieldMixin ],
name: 'ApostropheStringField',
methods: {
validate(value) {
if (this.field.required) {
if (!value.length) {
return 'required';
module.exports = {
props: {
value: Object,
field: Object,
context: Object
},
data() {
return {
next: (this.value.data !== undefined) ? this.value.data : (this.field.def || ''),
error: false
<template>
<ApostropheModal @close="$emit('close')">
<template slot="header">
<p>New {{ options.label }}</p>
</template>
<template slot="body">
<ApostropheSchemaEditor :fields="options.schema" v-model="pieceInfo" />
</template>
<template slot="footer">
<slot name="footer">