Skip to content

Instantly share code, notes, and snippets.

@ckunte
Created July 22, 2026 03:07
Show Gist options
  • Select an option

  • Save ckunte/a89ceca6b39f618e391a8168a88b74da to your computer and use it in GitHub Desktop.

Select an option

Save ckunte/a89ceca6b39f618e391a8168a88b74da to your computer and use it in GitHub Desktop.
Small caps
(function () {
var SKIP_TAGS = ['PRE', 'CODE', 'SCRIPT', 'STYLE', 'TEXTAREA', 'ABBR', 'KBD', 'SAMP'];
function isInSkippedAncestor(node) {
var el = node.parentElement;
while (el) {
if (SKIP_TAGS.indexOf(el.tagName) !== -1) return true;
el = el.parentElement;
}
return false;
}
function scotf(root) {
var walker = document.createTreeWalker(
root || document.body,
NodeFilter.SHOW_TEXT,
{
acceptNode: function (node) {
if (isInSkippedAncestor(node)) return NodeFilter.FILTER_REJECT;
return /[A-Z]{2,}/.test(node.nodeValue)
? NodeFilter.FILTER_ACCEPT
: NodeFilter.FILTER_SKIP;
}
}
);
var nodes = [];
var n;
while ((n = walker.nextNode())) nodes.push(n);
nodes.forEach(function (textNode) {
var parts = textNode.nodeValue.split(/([A-Z]{2,})/g);
if (parts.length === 1) return; // nothing matched
var frag = document.createDocumentFragment();
parts.forEach(function (part) {
if (!part) return;
if (/^[A-Z]{2,}$/.test(part)) {
var abbr = document.createElement('abbr');
abbr.textContent = part;
frag.appendChild(abbr);
} else {
frag.appendChild(document.createTextNode(part));
}
});
textNode.parentNode.replaceChild(frag, textNode);
});
}
window.addEventListener('load', function () { scotf(); });
// expose for manual re-runs on dynamically injected content
window.scotf = scotf;
})();
@ckunte

ckunte commented Jul 22, 2026

Copy link
Copy Markdown
Author

Styling to use together with the script above.

abbr {
  font-variant: small-caps;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment