Skip to content

Instantly share code, notes, and snippets.

@ngbrown
ngbrown / Count-Lines.ps1
Created October 10, 2025 16:11
Counts the lines of code in the specified directory using cloc. Uses PowerShell and Docker.
<#
.SYNOPSIS
Counts the lines of code in the specified directory using cloc.
.DESCRIPTION
This script utilizes the cloc (Count Lines of Code) tool to analyze and count the lines of code in a given directory. It requires Docker Desktop to be running, as cloc is executed within a Docker container.
To improve performance, the script first compresses the files into a zip archive. This allows the Docker container to analyze the code quickly, avoiding the slow performance that would result from mounting all files as a volume.
@ngbrown
ngbrown / entry.server.tsx
Last active August 30, 2024 07:25
Populate Links in Remix for Cloudflare 103 hints
/**
* By default, Remix will handle generating the HTTP Response for you.
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
* For more information, see https://remix.run/file-conventions/entry.server
*/
import type { AppLoadContext, EntryContext } from "@remix-run/cloudflare";
import { RemixServer } from "@remix-run/react";
import { isbot } from "isbot";
import { renderToReadableStream } from "react-dom/server";
@ngbrown
ngbrown / nav.tsx
Last active August 6, 2024 07:09
Nav for Remix (and React Router) - Use to drive which component has the active link in a menu
import React from "react";
import type { LinkProps } from "@remix-run/react";
import { stripBasename } from "@remix-run/router";
import {
UNSAFE_DataRouterStateContext as DataRouterStateContext,
UNSAFE_NavigationContext as NavigationContext,
useLocation,
useResolvedPath,
@ngbrown
ngbrown / SemaphoreSlimExtensions.cs
Created May 21, 2024 15:48
SemaphoreSlimExtensions
public static class SemaphoreSlimExtensions
{
/// <summary>
/// Blocks the current thread until it can enter the <see cref="SemaphoreSlim"/>. Returns an <see cref="IDisposable"/> to be used in <c>using</c>.
/// </summary>
/// <param name="semaphore">A <see cref="SemaphoreSlim"/> to lock.</param>
/// <returns>An <see cref="IDisposable"/> that will release the <see cref="SemaphoreSlim"/> when disposed.</returns>
public static IDisposable Lock(this SemaphoreSlim semaphore)
{
semaphore.Wait();
@ngbrown
ngbrown / Remix.xml
Last active April 9, 2024 20:50
WebStorm Live Template for Remix
<templateSet group="Remix">
<template name="useFetcher" value="const $fetcher$ = useFetcher();" description="const fetcher = useFetcher()" toReformat="true" toShortenFQNames="true" useStaticImport="true">
<variable name="fetcher" expression="" defaultValue="&quot;fetcher&quot;" alwaysStopAt="true" />
<context>
<option name="JS_CLASS_MEMBER_STATEMENT" value="false" />
<option name="JS_STATEMENT" value="true" />
<option name="TS_CLASS_MEMBER_STATEMENT" value="false" />
<option name="TS_STATEMENT" value="true" />
</context>
</template>
@ngbrown
ngbrown / svg-path-builder.ts
Last active April 14, 2024 18:06
SVG Path Builder (TypeScript)
// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#path_commands
// https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths
// M moveto (x y)+
// Z closepath (none)
// L lineto (x y)+
// H horizontal lineto x+
// V vertical lineto y+
// C curveto (x1 y1 x2 y2 x y)+
// S smooth curveto (x2 y2 x y)+
// Q quadratic Bézier curveto (x1 y1 x y)+
@ngbrown
ngbrown / download-git-powershell.md
Created January 10, 2024 17:44
Downloading Git for Windows PowerShell

To download Git with PowerShell:

Get most recent version URL from https://git-scm.com/download/win

cd "${env:USERPROFILE}\Downloads"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;
$ProgressPreference = 'SilentlyContinue';Invoke-WebRequest -Uri https://github.com/git-for-windows/git/releases/download/v2.43.0.windows.1/Git-2.43.0-64-bit.exe -OutFile Git-2.43.0-64-bit.exe
@ngbrown
ngbrown / client-only.tsx
Created December 27, 2023 18:58
Remix Client Only Component
import React, { ComponentType, lazy, Suspense } from "react";
export function ClientOnly({
fallback,
component,
}: {
fallback: React.ReactElement;
component: Promise<{ default: ComponentType<any> }>;
}) {
const LazyComponent = lazy(() => component);
@ngbrown
ngbrown / generate-fontawesome-icons.js
Created December 21, 2023 02:42
Generate TypeScript files containing Font Awsome Icons from kit metadata
#!/usr/bin/env node
/* eslint-env node */
import fs from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
async function main() {
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
@ngbrown
ngbrown / use-dynamic-throttle.ts
Last active August 19, 2023 17:10
useDynamicThrottle React hook
import { useCallback, useEffect, useRef, useState } from "react";
/**
* Returns a throttled version of the value and a function to release the next update, which may occur immediately or
* on the next value change.
*
* This can be used to keep the interface responsive when you have values that are changing too fast for async processes to keep up.
* @param value The value that is going to be throttled
*/
export function useDynamicThrottle<T>(