Skip to content

Instantly share code, notes, and snippets.

@impliedgg
Created August 9, 2026 15:44
Show Gist options
  • Select an option

  • Save impliedgg/70cf236a4e66b32ed3acb38e1c913e33 to your computer and use it in GitHub Desktop.

Select an option

Save impliedgg/70cf236a4e66b32ed3acb38e1c913e33 to your computer and use it in GitHub Desktop.
stackoverflow attribution minimizer
// ==UserScript==
// @name StackOverflow Minimized Attribution
// @namespace github@impliedgg
// @match https://stackoverflow.com/*
// @version 1.0
// @author github@impliedgg
// @description For StackOverflow. Reduces the attribution text for StackOverflow snippets to one line, while still citing the URL, author, date retrieved, and license.
// @grant GM_setClipboard
// ==/UserScript==
document.addEventListener('copy', function (e) {
function asComment(text, lang) {
let bestCandidate = null;
let parserContains = hljs.getLanguage(lang).contains;
for (let containedIdx in parserContains) {
let contained = parserContains[containedIdx];
if (contained.scope === 'comment') {
if (bestCandidate == null) {
bestCandidate = contained;
} else if (bestCandidate.end != '$' && contained.end == '$') {
bestCandidate = contained;
}
// if not prefix-only and not first, simply pass over this comment type
}
}
if (bestCandidate == null) {
return text; // pass through without commenting, you're on your own lmao
} else {
let begin = null;
let end = null;
// these are evil one-liners, but they: 1. convert regex begin/end tokens to strings 2. remove escaped backslashes...
if (typeof bestCandidate.begin === 'string') { begin = bestCandidate.begin.replace('\\', ''); } else { begin = String(bestCandidate.begin).replace(/^\//, '').replace(/\/$/, '').replace('\\', ''); }
if (typeof bestCandidate.end === 'string') { end = bestCandidate.end.replace('\\', ''); } else { end = String(bestCandidate.end).replace(/^\//, '').replace(/\/$/, '').replace('\\', ''); }
if (end == '$') {
return begin + ' ' + text; // just prefix
} else {
return begin + ' ' + text + ' ' + end; // prefix and suffix
}
}
}
// bypass logic if we're not copying from code element
if (e.srcElement.localName === 'code') {
// walk up DOM until we hit an element with .answer, which is always has *this* answer's data
let answerObject = e.srcElement.parentElement;
while (!answerObject.classList.contains('answer')) {
answerObject = answerObject.parentElement;
}
/*
* we want output as follows:
* commented: https://stackoverflow.com/a/idhere - username - YYYY-MM-DD - CC BY-SA 3.0
* snippet goes here.......
*/
let attributionText = `https://stackoverflow.com/a/${answerObject.dataset.answerid} - ${answerObject.dataset.authorUsername} - ${new Date().toISOString().slice(0, 10)} - CC BY-SA 3.0`;
let finalText = asComment(attributionText, e.srcElement.result.language) + '\n' + e.srcElement.textContent;
setTimeout(() => { GM_setClipboard(finalText, 'text/plain'); }, 50); // if we don't do this setTimeout the actual code overwrites our custom copy lmao
e.preventDefault();
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment