Skip to content

Instantly share code, notes, and snippets.

@victornpb
Created June 27, 2025 21:50
Show Gist options
  • Save victornpb/e593afba3678212dc89cf0b13351f950 to your computer and use it in GitHub Desktop.
Save victornpb/e593afba3678212dc89cf0b13351f950 to your computer and use it in GitHub Desktop.
Gist Install Button
// ==UserScript==
// @name Gist - Install Script Button
// @namespace http://github.com/victornpb
// @version 1.0
// @description Add “Install User Script” button to Gist pages for .user.js files without commit hash in URL
// @author Victor
// @match https://gist.github.com/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
function addInstallButtons() {
document.querySelectorAll('.file-header').forEach(header => {
const info = header.querySelector('.file-info');
if (!info) return;
const fileName = info.innerText.trim();
if (!fileName.endsWith('.user.js')) return;
const actions = header.querySelector('.file-actions');
if (!actions) return;
if (actions.querySelector('a[data-install-user-script]')) return;
const rawLink = actions.querySelector('a[href*="/raw/"]');
if (!rawLink) return;
const href = rawLink.getAttribute('href');
const parts = href.split('/');
const rawIndex = parts.indexOf('raw');
if (rawIndex < 0) return;
const newParts = parts.slice(0, rawIndex + 1).concat(parts.slice(rawIndex + 2));
const installHref = newParts.join('/');
const btn = document.createElement('a');
btn.setAttribute('href', installHref);
btn.setAttribute('data-view-component', 'true');
btn.setAttribute('data-install-user-script', 'true');
btn.className = rawLink.className;
btn.innerHTML = `
<span class="Button-content">
<span class="Button-label">Install User Script</span>
</span>
`;
actions.prepend(btn);
});
}
function onUrlChange() {
addInstallButtons();
}
const _pushState = history.pushState;
history.pushState = function() {
_pushState.apply(this, arguments);
window.dispatchEvent(new Event('locationchange'));
};
const _replaceState = history.replaceState;
history.replaceState = function() {
_replaceState.apply(this, arguments);
window.dispatchEvent(new Event('locationchange'));
};
window.addEventListener('popstate', () => {
window.dispatchEvent(new Event('locationchange'));
});
window.addEventListener('locationchange', onUrlChange);
window.addEventListener('DOMContentLoaded', onUrlChange);
addInstallButtons();
})();
@victornpb
Copy link
Author

Adds a "Install" button to any Gist page that has *.user.js file

image

Whats the difference from the "Raw" button?

Differently from Raw, this will install from an URL that lets the extension fetch for updates.

Raw link points to a specific commit, the installed version won't update if the script changes.

If you want your extension to be up to date with the gist, use the Install button, if you don't trust the source for future changes use the Raw button.

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