Skip to content

Instantly share code, notes, and snippets.

@noromanba
Last active September 2, 2023 13:03
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save noromanba/2370972 to your computer and use it in GitHub Desktop.
Save noromanba/2370972 to your computer and use it in GitHub Desktop.
add permanently HEAD links on Gist for UserScript

gist raw perm HEAD

Install

About

Visit Gist and see 'raw' link, It's including SHA-1 long hash name like this.

https://gist.github.com/raw/2370972/47150711fedb7375d19d761ab122485b8105678d/gist-raw-perm-HEAD.user.js

gist-raw-HEAD

This user.js provide 'HEAD' links. It's takes shrinked permanent raw link and shrinked named raw link when you browse Gist files.

HEAD

True Permalink: This is absolutery permanent link but it's always filetype: txt.

https://gist.github.com/raw/2370972/

HEAD(named)

Almost Permalink: This is almost permanent link. It's strict filetype by extension. This link broken when filename changed.

https://gist.github.com/raw/2370972/gist-raw-perm-HEAD.user.js

This link most useful for install user.js from Gist.

Known Problems

Multifiles Gist

HEAD can accessible 1st file only. That is Gist API constraints.

Binary 1st file

e.g. https://gist.github.com/890279/

prob SOLVED, sort alphabetic? and text file order are top access to raw https://gist.github.com/raw/890279/ expected https://raw.github.com/gist/890279/simple320_320.png but actual API return 2nd text file data.

Gist API

Multifiles Gist has problem. Gist API is not provide true permalink(called HEAD) for 2nd or more files.

Include content and history. it's too long too much than v1(closed).

See also

Gist HTTP

e.g. https://gist.github.com/2370972

OBSOLETE

  • GET 'raw' => HTTP 302

https://gist.github.com/raw/2370972/2370972/47150711fedb7375d19d761ab122485b8105678d/gist-raw-perm-HEAD.user.js

  • => HTTP 200 OK

https://raw.github.com/gist/2370972/2370972/47150711fedb7375d19d761ab122485b8105678d/gist-raw-perm-HEAD.user.js

Bookmarklet

base code is small Bookmarklet, you can see based rev below

// ==UserScript==
// @name gist raw perm HEAD
// @namespace http://www.hatena.ne.jp/noromanba/
// @description add permanently HEAD link on Gist for UserScript
// @include https://gist.github.com/*
// @exclude https://gist.github.com/*/*/revisions
// @grant none
// @version 2014.12.20.0
// @homepage https://gist.github.com/2370972
// @downloadURL https://gist.github.com/noromanba/2370972/raw/gist-raw-perm-HEAD.user.js
// @license MIT License http://nrm.mit-license.org/2012
// @author noromanba http://noromanba.flavors.me
// @icon https://upload.wikimedia.org/wikipedia/commons/thumb/9/9b/Color_icon_orange_v2.svg/32px-Color_icon_orange_v2.svg.png
// @icon64 https://upload.wikimedia.org/wikipedia/commons/thumb/9/9b/Color_icon_orange_v2.svg/64px-Color_icon_orange_v2.svg.png
// ==/UserScript==
// Icon (PD by Mizunoryu, Badseed, Jacobolus)
// https://commons.wikimedia.org/wiki/File:Color_icon_orange_v2.svg
// Devel
// https://gist.github.com/2370972
(function () {
// WIP
// - [x] works well onload/DOMContentLoaded
// - [ ] pjax:success/end handling
// - can not use executeBrowserContext() (aka contentEval et al.)
// - due to CSP, too much strict
// - so can not touch page-context jQuery
var appendButton = function code() {
var links;
if (!/^https:\/\/gist\.github\.com\/[\w-]+\/\w+/.test(location.href) ||
!(links = document.body.querySelectorAll('.files .raw-url:not(.head-url)'))) {
return;
}
Array.prototype.forEach.call(links, function (hashlink) {
// <a aria-label="View Raw" href="/noromanba/2370972/raw/431c256a6a929a15867112d93bc82238a2723a47/README.md" data-skip-pjax="" class="minibutton raw-url js-view-raw">Raw</a>
var perm = document.createElement('a');
perm.textContent = 'HEAD';
perm.ariaLabel = 'View HEAD';
perm.dataset.skipPjax = '';
perm.classList.add('minibutton', 'head-url');
var pathnames = hashlink.href.split('/');
var filename = pathnames.pop();
var base = pathnames.slice(0, -1).join('/');
perm.title = filename;
//perm.textContent = filename;
perm.href = base + '/' + filename;
hashlink.parentNode.appendChild(perm);
});
};
appendButton();
// FIXME faild due to CSP, work w/ executeBrowserContext()
/*/
// TODO independent of jQuery; replace to MutationObserver
// c.f. https://github.com/defunkt/jquery-pjax#events
jQuery('#js-pjax-container').on('pjax:end', function () {
appendButton();
});
//*/
// FIXME 100% cpu usage
/*/
// c.f. MutationObserver
// https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
// http://caniuse.com/#feat=mutationobserver
new MutationObserver(function (records) {
//records.forEach(function (record) {
appendButton();
//});
}).observe(document.body, { childList: true, subtree: true });
//*/
////////////////////////////////////////////////////////////////////////////
// DBG pjax handling
// - https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js
// - https://raw.github.com/defunkt/jquery-pjax/master/jquery.pjax.js
/*/
window.addEventListener('load', function (evt) {
console.info(evt.type, evt);
}, false);
window.addEventListener('popstate', function (evt) {
console.info(evt.type, evt);
}, false);
// c.f. https://github.com/defunkt/jquery-pjax#events
window.addEventListener('pjax:start', function (evt) {
console.log(evt.type, evt);
}, false);
window.addEventListener('pjax:end', function (evt) {
console.log(evt.type, evt);
}, false);
window.addEventListener('pjax:beforeSend', function (evt) {
console.log(evt.type, evt);
}, false);
window.addEventListener('pjax:send', function (evt) {
console.log(evt.type, evt);
}, false);
window.addEventListener('pjax:complete', function (evt) {
console.log(evt.type, evt);
}, false);
window.addEventListener('pjax:success', function (evt) {
console.log(evt.type, evt);
}, false);
window.addEventListener('pjax:error', function (evt) {
console.log(evt.type, evt);
}, false);
window.addEventListener('pjax:timeout', function (evt) {
console.log(evt.type, evt);
}, false);
window.addEventListener('pjax:send', function (evt) {
console.log(evt.type, evt);
}, false);
// $.pjax.submit only use of Gist c.f. https://github.com/defunkt/jquery-pjax#pjaxsubmit
window.addEventListener('submit', function (evt) {
console.log(evt.type, evt);
}, false);
////////// jQuery .on //////////
// c.f. https://github.com/defunkt/jquery-pjax#events
$(document).on('pjax:start', function (evt) {
console.log(evt.type, evt);
});
$(document).on('pjax:end', function (evt) {
console.log(evt.type, evt);
});
$(document).on('pjax:beforeSend', function (evt) {
console.log(evt.type, evt);
});
$(document).on('pjax:send', function (evt) {
console.log(evt.type, evt);
});
$(document).on('pjax:complete', function (evt) {
console.log(evt.type, evt);
});
$(document).on('pjax:success', function (evt) {
console.log(evt.type, evt);
});
$(document).on('pjax:error', function (evt) {
console.log(evt.type, evt);
});
$(document).on('pjax:timeout', function (evt) {
console.log(evt.type, evt);
});
$(document).on('pjax:send', function (evt) {
console.log(evt.type, evt);
});
$(document).on('submit', function (evt) {
console.log(evt.type, evt);
});
// #js-pjax-container
$('#js-pjax-container').on('submit', function (evt) {
console.log(evt.type, evt);
});
$('#js-pjax-container').on('pjax:start', function (evt) {
console.log(evt.type, evt);
});
$('#js-pjax-container').on('pjax:end', function (evt) {
console.log(evt.type, evt);
});
$('#js-pjax-container').on('pjax:beforeSend', function (evt) {
console.log(evt.type, evt);
});
$('#js-pjax-container').on('pjax:send', function (evt) {
console.log(evt.type, evt);
});
$('#js-pjax-container').on('pjax:complete', function (evt) {
console.log(evt.type, evt);
});
$('#js-pjax-container').on('pjax:success', function (evt) {
console.log(evt.type, evt);
});
$('#js-pjax-container').on('pjax:error', function (evt) {
console.log(evt.type, evt);
});
$('#js-pjax-container').on('pjax:timeout', function (evt) {
console.log(evt.type, evt);
});
$('#js-pjax-container').on('pjax:send', function (evt) {
console.log(evt.type, evt);
});
$('#js-pjax-container').on('submit', function (evt) {
console.log(evt.type, evt);
});
//*/
})(); // /anonwrap
@LouCypher
Copy link

The new Gist broke your script \( ><)シ

@noromanba
Copy link
Author

@LouCypher
thank you for your infomation :-)

broken

I know, maybe gist API changes too. but GitHub not provide information. hum..
a similar kind as shown below

feed => HTTP406

can't get gists feed

https://gist.github.com/noromanba.atom

Subscribe Gists - Hatena::Let

i.e. mulfunction open feed on flavors.me

blame UI

where is panel which put log?

too drastic.. I’m stucking X-(
I don't have much time now, a correction takes time.

FYI

didn't notification by Github, I'm late.
try @USERNAME with comments

Regards,
noromanba

@noromanba
Copy link
Author

@LouCypher
quick fix 🚑 now. but incompletly yet. pjax handling.........🐌
if unworks it, plz try reload

@LouCypher
Copy link

Thanks for the updates
       «:dancers::dancers:ヾ

@noromanba
Copy link
Author

@LouCypher
somehow handle pjax:sleepy::dizzy: thx for your patience:pray:

@jerone
Copy link

jerone commented Jan 29, 2013

Would be great if you get this to work with the new style and upload new version to USO.

@noromanba
Copy link
Author

stuck in... 💭 take away freedom by CSP 🔒

@noromanba
Copy link
Author

@jerone sry I'm late. thx. USO has gone, and fork sites not good enough. e.g. GF; extreme security

@denilsonsa
Copy link

Hey, @noromanba, I've updated the script to work on the current GitHub markup. Look at https://gist.github.com/denilsonsa/f2e5b9ee53e633e20165 and please update your version. :)

@denilsonsa
Copy link

FYI, it was broken again, and I've fixed it again: https://gist.github.com/denilsonsa/f2e5b9ee53e633e20165

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