Skip to content

Instantly share code, notes, and snippets.


Don McCurdy donmccurdy

View GitHub Profile

Pure ESM package

The package linked to from here is now pure ESM. It cannot be require()'d from CommonJS.

This means you have the following choices:

  1. Use ESM yourself. (preferred)
    Use import foo from 'foo' instead of const foo = require('foo') to import the package. You also need to put "type": "module" in your package.json and more. Follow the below guide.
  2. If the package is used in an async context, you could use await import(…) from CommonJS instead of require(…).
  3. Stay on the existing version of the package until you can move to ESM.
donmccurdy /
Last active May 5, 2022
Initialization order and public class properties

Initialization order and public class properties


class Parent {
    constructor() {
donmccurdy / bin-plugin.js
Last active Apr 7, 2022
Example vite/rollup plugin for processing binary files.
View bin-plugin.js
import { createFilter, normalizePath } from "@rollup/pluginutils";
import fs from "fs/promises";
import crypto from "crypto";
import path from "path";
const PLUGIN_NAME = "bin";
const HASH_LENGTH = 8;
donmccurdy / create-basic-glb.js
Created Feb 27, 2022
Create a basic GLB with a single mesh.
View create-basic-glb.js
import { Accessor, Document, Primitive, NodeIO } from '@gltf-transform/core';
const document = new Document();
const prim = document.createPrimitive();
const buffer = document.createBuffer();
const material = document.createMaterial()
.setBaseColorFactor([1.0, 0.0, 0.0, 1.0])
donmccurdy / flat-normals.ts
Last active Feb 12, 2022
Compute flat normals in glTF-Transform
View flat-normals.ts
import { vec3 } from 'gl-matrix';
import { unweld } from '@gltf-transform/functions';
await document.transform(unweld());
for (const mesh of document.getRoot().listMeshes()) {
for (const prim of mesh.listPrimitives()) {
const position = prim.getAttribute('POSITION');
const normal = document.createAccessor()
.setArray(new Float32Array(position.getCount() * 3))
donmccurdy /
Last active Sep 21, 2021
Divide glTF Document

Divide glTF Document

Example script showing how to use glTF-Transform ( to divide a glTF asset — along an axis — into two GLBs, each occupying half the original bounding box. This is just a rough illustration, and has only been tested against a point cloud containing a single mesh. A production implementation would want to do more than this:

  • support >2 divisions
  • for primitives that lie fully in one division, don't write an empty primitive to the others
  • support triangles, lines, etc.

For input with significant outliers (e.g. noisy point clouds), dividing by the center of the bounding box may give unexpected results.

donmccurdy /
Last active Sep 21, 2021
Meshopt Compression and Tabular Data

Evaluation: Meshopt Compression with Tabular Data

Summary: Short evaluation of Meshopt compression for use with tabular data. For the purposes of this evaluation, tabular data is defined as a dataset having many observations ("rows"), where each observation consists of one or more property values from a common schema.


I downloaded the results of the 2015 NYC Tree Census from BigQuery's NYC Street Trees public dataset, also available through NYC Open Data. The 2015 census consists of 683,788 rows and 41 columns, and is about 500 MB when exported as JSON. Much of that data is text, and because meshopt is designed for numeric input we have good reason to believe results for the numeric columns will be "at least as good" as results for the dataset as a whole. For purposes of simpler evaluation and an upper bound on compre

donmccurdy /
Last active Sep 14, 2021
EXT_feature_metadata: Optional and Nullable Values

(1) Optional Property Column

Already defined in schema.

(2) Optional Property Value

noData: NoData values represent missing data (also known as sentinel values). If omitted, property values are considered to be present for all features — with the exception of variable-length ARRAY elements, which may be left empty without a NoData value.

"classes": {
donmccurdy / format_libby_highlights.js
Created Jun 24, 2021
Script for formatting Libby highlights as Markdown.
View format_libby_highlights.js
const fs = require('fs');
const json = require('./name_of_book.json');
let md = '';
let lastChapter = '';
json.highlights.sort((a, b) => a.percent - b.percent);
for (const highlight of json.highlights) {
if (lastChapter !== highlight.chapter) {