Skip to content

Instantly share code, notes, and snippets.

View philwolstenholme's full-sized avatar

Phil Wolstenholme philwolstenholme

View GitHub Profile
@philwolstenholme
philwolstenholme / renderServerComponent.ts
Created November 20, 2025 11:20 — forked from sroebert/renderServerComponent.ts
A (hacky) way to render server components for React testing library.
import type { PropsWithChildren, ReactElement, ReactNode } from 'react';
import React, { Children, cloneElement, isValidElement } from 'react';
import { render } from '@testing-library/react';
function setFakeReactDispatcher<T>(action: () => T): T {
/**
* We use some internals from React to avoid a lot of warnings in our tests when faking
* to render server components. If the structure of React changes, this function should still work,
* but the tests will again print warnings.
@philwolstenholme
philwolstenholme / renderServerComponent.ts
Created November 20, 2025 11:20 — forked from sroebert/renderServerComponent.ts
A (hacky) way to render server components for React testing library.
import type { PropsWithChildren, ReactElement, ReactNode } from 'react';
import React, { Children, cloneElement, isValidElement } from 'react';
import { render } from '@testing-library/react';
function setFakeReactDispatcher<T>(action: () => T): T {
/**
* We use some internals from React to avoid a lot of warnings in our tests when faking
* to render server components. If the structure of React changes, this function should still work,
* but the tests will again print warnings.
@philwolstenholme
philwolstenholme / replaceClassNames.js
Created October 21, 2025 11:51
Disclosure: this is from GTP-5 but I've tested it in a browser
/**
* Replace text inside class attributes across the DOM (allows partial matches).
*
* @param {string} find - Text to find inside class attribute (partial allowed).
* @param {string} replaceWith - Replacement text.
* @param {Object} [options]
* @param {HTMLElement|Document|Element} [options.scope=document] - Limit to a subtree.
* @returns {number} Count of elements that were modified.
*/
function replaceClassNames(find, replaceWith, { scope = document } = {}) {
import { UAParser } from "ua-parser-js";
/**
* Uses the `Sec-CH-UA-Mobile` header if it's available to work out how many
* items to show per page.
*/
export const getItemsPerPage = ({
astroRequest,
mobileItemsPerPage = 5,
desktopItemsPerPage = 12,
{# List out all the classes we *may* want to use, so they are not purged #}
{% set spacing_levels = {
1: 'u-o-1',
2: 'u-o-2',
3: 'u-o-3',
4: 'u-o-4',
5: 'u-o-5',
6: 'u-o-6',
7: 'u-o-7',
8: 'u-o-8',
<img
style="
background: no-repeat center/cover
url('data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' xmlns:xlink=\'http://www.w3.org/1999/xlink\' viewBox=\'0 0 50 50\'%3e %3cfilter id=\'b\' color-interpolation-filters=\'sRGB\'%3e %3cfeGaussianBlur stdDeviation=\'.9\'%3e%3c/feGaussianBlur%3e %3cfeComponentTransfer%3e %3cfeFuncA type=\'discrete\' tableValues=\'1 1\'%3e%3c/feFuncA%3e %3c/feComponentTransfer%3e %3c/filter%3e %3cimage filter=\'url%28%23b%29\' preserveAspectRatio=\'none\' height=\'100%25\' width=\'100%25\' xlink:href=\'data:image/png%3bbase64%2ciVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAIAAAASFvFNAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAHElEQVQImWNsbulgZPjHzc3PcvvOXYb/f/n4hABJ6gd39LTd2AAAAABJRU5ErkJggg==\'%3e %3c/image%3e %3c/svg%3e');
"
data-blurhash
src="/sites/default/files/2021-03/photo-1485304018316-1ff471aa1369.jpeg"
width="2850"
height="1900"
alt="Fire"
@philwolstenholme
philwolstenholme / example.js
Last active December 23, 2020 20:02
One example of working around the '100vw includes scrollbar width' issue
const width = window.innerWidth - document.documentElement.clientWidth;
const root = document.documentElement;
root.style.setProperty('--scrollbar-width', `${width}px`);
@philwolstenholme
philwolstenholme / ######-phil-wolstenholme-drupalcon-europe-2020-utility-first-css.md
Last active November 1, 2021 09:18
Phil Wolstenholme - DrupalCon Europe 2020 - Utility-first CSS

Hello DrupalCon! 👋

Here's a big dump of code examples from my slides, plus some examples that didn't make it to the final cut.

The snippets should be organised by slide number, e.g. #46--_search.scss is the snippet of search-related SCSS shown on slide 46.

My slides

Here's a PDF of my slides (via Google Drive) for your reference, or if Zoom goes wrong!

(function randomSkinTone() {
const fitzPatrickTones = [
'#ffe2cc',
'#fadbaf',
'#e5bd95',
'#bf8b60',
'#98562e',
'#673929',
];