Skip to content

Instantly share code, notes, and snippets.

@philwolstenholme
Created October 21, 2025 11:51
Show Gist options
  • Select an option

  • Save philwolstenholme/b853a170a97f33835aa148045db96a55 to your computer and use it in GitHub Desktop.

Select an option

Save philwolstenholme/b853a170a97f33835aa148045db96a55 to your computer and use it in GitHub Desktop.
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 } = {}) {
if (typeof find !== 'string' || find.length === 0) return 0;
// Escape regex metacharacters in `find`.
const escapeRegExp = s => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const re = new RegExp(escapeRegExp(find), 'g');
let changed = 0;
scope.querySelectorAll('[class]').forEach(el => {
// Always read from the attribute so it works for SVG (className may be an object).
const before = el.getAttribute('class');
if (typeof before !== 'string' || before.length === 0) return;
// Partial replace within the full class attribute string.
let after = before.replace(re, replaceWith);
if (after !== before) {
// Normalize whitespace and dedupe class tokens.
after = after.trim().replace(/\s+/g, ' ');
const deduped = Array.from(new Set(after.split(/\s+/).filter(Boolean))).join(' ');
// Always write back via attribute to keep behavior consistent across HTML/SVG.
el.setAttribute('class', deduped);
changed++;
}
});
return changed;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment