Github Gist Share

Share your GitHub Gist to Twitter, Dabblet, Bl.ocks & as userscript.

  1. // ==UserScript==
  2. // @name Github Gist Share
  3. // @namespace https://github.com/jerone/UserScripts/
  4. // @description Share your GitHub Gist to Twitter, Dabblet, Bl.ocks & as userscript.
  5. // @author jerone
  6. // @copyright 2014+, jerone (https://github.com/jerone)
  7. // @license CC-BY-NC-SA-4.0; https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
  8. // @license GPL-3.0-or-later; http://www.gnu.org/licenses/gpl-3.0.txt
  9. // @homepage https://github.com/jerone/UserScripts/tree/master/Github_Gist_Share
  10. // @homepageURL https://github.com/jerone/UserScripts/tree/master/Github_Gist_Share
  11. // @supportURL https://github.com/jerone/UserScripts/issues
  12. // @contributionURL https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=VCYMHWQ7ZMBKW
  13. // @icon https://github.githubassets.com/pinned-octocat.svg
  14. // @include *://gist.github.com/*
  15. // @version 5.1
  16. // @grant none
  17. // ==/UserScript==
  18.  
  19. // cSpell:ignore Dabblet, Bl.ocks, itemprop, tweetbutton
  20. /* eslint security/detect-object-injection: "off" */
  21.  
  22. (function () {
  23. String.format = function (string) {
  24. const args = Array.prototype.slice.call(arguments, 1, arguments.length);
  25. return string.replace(/{(\d+)}/g, function (match, number) {
  26. return typeof args[number] !== "undefined" ? args[number] : match;
  27. });
  28. };
  29.  
  30. function Menu(container) {
  31. const div$0$0 = document.createElement("div");
  32. div$0$0.classList.add("file-navigation-option");
  33. div$0$0.id = "Github_Gist_Share";
  34. container.insertBefore(div$0$0, container.firstChild);
  35.  
  36. const div$1$0 = document.createElement("div");
  37. div$1$0.classList.add(
  38. "select-menu",
  39. "js-menu-container",
  40. "select-menu-modal-left",
  41. "js-select-menu",
  42. );
  43. div$0$0.appendChild(div$1$0);
  44.  
  45. const button$2$0 = document.createElement("button");
  46. button$2$0.classList.add(
  47. "btn",
  48. "btn-sm",
  49. "select-menu-button",
  50. "icon-only",
  51. "js-menu-target",
  52. );
  53. button$2$0.setAttribute("type", "button");
  54. div$1$0.appendChild(button$2$0);
  55.  
  56. const svg$3$0 = document.createElementNS(
  57. "http://www.w3.org/2000/svg",
  58. "svg",
  59. );
  60. svg$3$0.classList.add("octicon", "octicon-link-external");
  61. svg$3$0.setAttributeNS(null, "height", 16);
  62. svg$3$0.setAttributeNS(null, "version", "1.1");
  63. svg$3$0.setAttributeNS(null, "viewBox", "0 0 12 16");
  64. svg$3$0.setAttributeNS(null, "width", 12);
  65. button$2$0.appendChild(svg$3$0);
  66.  
  67. const path$4$0 = document.createElementNS(
  68. "http://www.w3.org/2000/svg",
  69. "path",
  70. );
  71. path$4$0.setAttributeNS(
  72. null,
  73. "d",
  74. "M11 10h1v3c0 .55-.45 1-1 1H1c-.55 0-1-.45-1-1V3c0-.55.45-1 1-1h3v1H1v10h10v-3zM6 2l2.25 2.25L5 7.5 6.5 9l3.25-3.25L12 8V2H6z",
  75. );
  76. svg$3$0.appendChild(path$4$0);
  77.  
  78. button$2$0.appendChild(document.createTextNode(" Share "));
  79.  
  80. const div$2$1 = document.createElement("div");
  81. div$2$1.classList.add("select-menu-modal-holder");
  82. div$1$0.appendChild(div$2$1);
  83.  
  84. const div$3$0 = document.createElement("div");
  85. div$3$0.classList.add(
  86. "select-menu-modal",
  87. "select-menu-modal",
  88. "js-menu-content",
  89. );
  90. div$2$1.appendChild(div$3$0);
  91.  
  92. const div$4$0 = document.createElement("div");
  93. div$4$0.classList.add("select-menu-header");
  94. div$3$0.appendChild(div$4$0);
  95.  
  96. const svg$5$0 = document.createElementNS(
  97. "http://www.w3.org/2000/svg",
  98. "svg",
  99. );
  100. svg$5$0.classList.add("octicon", "octicon-x", "js-menu-close");
  101. svg$5$0.setAttributeNS(null, "height", 16);
  102. svg$5$0.setAttributeNS(null, "version", "1.1");
  103. svg$5$0.setAttributeNS(null, "viewBox", "0 0 12 16");
  104. svg$5$0.setAttributeNS(null, "width", 12);
  105. div$4$0.appendChild(svg$5$0);
  106.  
  107. const path$6$0 = document.createElementNS(
  108. "http://www.w3.org/2000/svg",
  109. "path",
  110. );
  111. path$6$0.setAttributeNS(
  112. null,
  113. "d",
  114. "M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z",
  115. );
  116. svg$5$0.appendChild(path$6$0);
  117.  
  118. const span$5$1 = document.createElement("span");
  119. span$5$1.classList.add("select-menu-title");
  120. div$4$0.appendChild(span$5$1);
  121.  
  122. span$5$1.appendChild(document.createTextNode("Share Gist with…"));
  123.  
  124. const div$4$1 = document.createElement("div");
  125. div$4$1.classList.add("select-menu-list", "js-navigation-container");
  126. div$3$0.appendChild(div$4$1);
  127.  
  128. this.itemsContainer = div$4$1;
  129. }
  130.  
  131. Menu.prototype.AddItem = function (text, title, href, icon, newTab) {
  132. const a = document.createElement("a");
  133. a.classList.add("select-menu-item", "js-navigation-item");
  134. a.setAttribute("href", href);
  135. if (title) a.setAttribute("title", title);
  136. if (newTab) a.setAttribute("target", "_blank");
  137. this.itemsContainer.appendChild(a);
  138.  
  139. const i = document.createElement("img");
  140. i.classList.add("select-menu-item-icon");
  141. i.setAttribute("src", icon);
  142. a.appendChild(i);
  143.  
  144. const s = document.createElement("span");
  145. s.classList.add("select-menu-item-text");
  146. a.appendChild(s);
  147.  
  148. s.appendChild(document.createTextNode(text));
  149. };
  150.  
  151. function getValue(elm) {
  152. return elm ? elm.textContent.trim() : "";
  153. }
  154.  
  155. function getIntValue(elm) {
  156. return elm ? parseInt(elm.textContent.trim(), 10) : 0;
  157. }
  158.  
  159. function addMenu() {
  160. const link = document.querySelector(".gist-header-title a");
  161. const nav = document.querySelector(".file-navigation-options");
  162. if (link && nav) {
  163. // Check if we're on an actual gist
  164. const data = {
  165. url: link.href,
  166. user: getValue(
  167. document.querySelector(".header-nav-current-user strong"),
  168. ),
  169. author: getValue(
  170. document.querySelector('.author [itemprop="author"]'),
  171. ),
  172. description: getValue(
  173. document.querySelector(".repository-meta-content") || link,
  174. ),
  175. files: document.querySelectorAll(".file").length,
  176. stars: getIntValue(
  177. document.querySelector(
  178. 'a[href$="/stargazers"] .counter, form[action$="/star"] .social-count',
  179. ),
  180. ),
  181. forks: getIntValue(
  182. document.querySelector(
  183. 'a[href$="/forks"] .counter, form[action$="/fork"] .social-count',
  184. ),
  185. ),
  186. revisions: getIntValue(
  187. document.querySelector('a[href$="/revisions"] .counter'),
  188. ),
  189. };
  190.  
  191. console.log(data);
  192.  
  193. const menu = new Menu(nav);
  194.  
  195. // Twitter
  196. // eslint-disable-next-line no-constant-condition
  197. if (true) {
  198. const stats = [];
  199. if (data.files > 1) {
  200. stats.push(data.files + " files");
  201. }
  202. if (data.stars === 1) {
  203. stats.push(data.stars + " star");
  204. } else if (data.stars > 1) {
  205. stats.push(data.stars + " stars");
  206. }
  207. if (data.forks === 1) {
  208. stats.push(data.forks + " fork");
  209. } else if (data.forks > 1) {
  210. stats.push(data.forks + " forks");
  211. }
  212. if (data.revisions > 1) {
  213. stats.push(data.revisions + " revisions");
  214. }
  215.  
  216. const tweet = String.format(
  217. "Check out {0} #gist {1} on @github {2}",
  218. data.author === data.user ? "my" : data.author + "'s",
  219. data.description ? '"' + data.description + '"' : "",
  220. stats.length > 0
  221. ? String.format("- {0} -", stats.join(", "))
  222. : "-",
  223. );
  224.  
  225. const link =
  226. "https://twitter.com/intent/tweet" +
  227. "?original_referer=" +
  228. encodeURIComponent(data.url) +
  229. "&source=tweetbutton&url=" +
  230. encodeURIComponent(data.url) +
  231. "&text=" +
  232. encodeURIComponent(tweet);
  233.  
  234. const icon =
  235. "data:image/vnd.microsoft.icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAD///8A////A////xT///8f////K////yj///8f////FP///wP///8A////AP///wD///8A////AP///wD///8A////H/357kj55K589tV+ofPFUML0y1+29tV+ofnkrnz9+e5I////H////wP///8A////AP///wD///8A////ANi/foG2iBDuvYkA/9CWAP/npwD/7qwA/+6sAP/urAD/7rAP8/bVfqH9+e8/////A////wD///8A////AP///wD///8A////APDnzjDjx36N3Kcf5e6sAP/urAD/7qwA/+6sAP/urAD/8bww2/357z////8D////AP///wD///8A////AP///wP///8z+N+eifTLX7burAD/7qwA/+6sAP/urAD/7qwA/+6sAP/xvDDb/PjvM////wD///8A////AP///wD69+8V2Kkw1eqpAP/urAD/7qwA/+6sAP/urAD/7qwA/+6sAP/urAD/7qwA//TLX7b///8H////AP///wD///8A+fLfPvbVfqHusA/z7qwA/+6sAP/urAD/7qwA/+6sAP/urAD/7qwA/+6sAP/urAD/+fLfPv///wD///8A////DPXQcKvurAD/7qwA/+6sAP/urAD/7qwA/+6sAP/urAD/7qwA/+6sAP/urAD/7qwA/+/Lb6f///8A////APPpzzzUmQD/7qwA/+6sAP/urAD/7qwA/+enAP/npwD/7qwA/+6sAP/urAD/7qwA/+6sAP/xvDDb////AP///wDt4L5G9dBwq+6sAP/urAD/2JwA/7qGAP+7kCDe1qMf4+6sAP/urAD/7qwA/+6sAP/urAD/7qwA/////yT///8A9/DeLu6sAP/npwD/vYkA/8+wYJ/1794f////AOXIfo7urAD/7qwA/+6sAP/urAD/7qwA/+6sAP/zznCo////KO7hv0jjpAD/vpIf4PDnzjD///8A////AP///wDeyI5x46QA/+6sAP/urAD/7qwA/+qpAP/UmQD/5KkO89u4YKfw584ww5ov0Pr37g////8A////AP///wD///8A+vfuD8OaL9DUmQD/36EA/9icAP+9jA/w07hwjsCYMM/p2a9U////APr37g////8A////AP///wD///8A////AP///wD69+4P07hwjsWgQL/PsGCf9e/eH////wD///8A9e/eH////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A//8AAOH/AAAAPwAA4B8AAOAPAADABwAAwAcAAIADAACAAwAAgAMAAIYBAACfAAAAvwEAAP+PAAD//wAA//8AAA==";
  236.  
  237. menu.AddItem(
  238. "Twitter",
  239. tweet + " " + data.url,
  240. link,
  241. icon,
  242. true,
  243. );
  244. }
  245.  
  246. // Userscripts
  247. if (
  248. document.querySelector(
  249. '.file .file-actions a[href$=".user.js" i]',
  250. )
  251. ) {
  252. const icon =
  253. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKwSURBVHjabJNJTBNRGID/mc5MQYVWVNCGTbEtNZGDBj1ogolEMR5UJA2LBmMoIokxERIj8ehJjx6MYIQoJgq4JIa6gEARkKJFTa2iFFtKWwp2oeDCzNQ+31DQCc5L/nmT/P/3749ACAFBECBxiEPFFds0Ws399DRVhtX2udc97ig0PmgOLBkIbOwjAR8uMRRdvXF7pqv/NfrqnEAOlxsdLas6j3Wk2AEpCRcbKvLydrdu1WUr0lXrITEhAZKUSkhQKvKwXiY2ppbDRzCcv29P/ZZsDaSqUkCJYVJGwKMnHTDlmWgTZ/CvjkW4sKTScP1WC+oZsKAxpwv5gyEUnAkj2xc70p88Y8Y2a8VBxT0gispOGa413UVDb23IMe6OwaEw+jTqQKMOF3pptqBSw7k74hLEPaDUOu0VmpFDV58ZCJIAkiDB5fUBz0eApmjQqbOgrqa69HhVbZO4jKUfmiBJBctysHJFPPiDYbA7J4DjeJDLaWAYGVAyErIy0uDs6RPH9OXVtULWYgfEmN3emJK8BlYrEsHl8cEvloX4ODnEyRlgKGZhV1iOhcz0VNixM7dOCCp2EBkeMF3u6DaNqDasg1U4CzlFxxSRKMyz8xjmsPAQwNmRsc2jxGPkR0esHp7n9RBFrYbyUi1DUzh1GujFG0UBQrNz8P7DR3j+9NklqTEK3VVkbNLkVNZc9AwNW5Hb60PT/gCamg6gEbsT3XvYjvIP6i9gu2ShhOWb+BvLD13O9o3azWrVdy4K3wKhv5HfWW1Q39BY19nechPbzQrVwX9bhU+iIqnyQMF+mPvJQr/FCsHwDJgG30ADhl8Y2wQ4jIUVkpdaZRnPcd6AfxomJ32AIhEwdvaC8XG7JLwwvmXPmVFn52Tu2lvQjN9Crn3M6bWY+6otr3oGpWCB/SPAAJaJRguGUxB0AAAAAElFTkSuQmCC";
  254. const userscripts = document.querySelectorAll(
  255. '.file .file-actions a[href$=".user.js"]',
  256. );
  257. Array.prototype.forEach.call(
  258. userscripts,
  259. function (userscript) {
  260. const text = String.format(
  261. 'Userscript "{0}"',
  262. userscript.href.split("/").pop(),
  263. );
  264. menu.AddItem(text, null, userscript.href, icon, false);
  265. },
  266. );
  267. }
  268.  
  269. // Dabblet
  270. if (
  271. document.querySelector(
  272. ".file .type-css, .file .type-html, .file .type-javascript",
  273. )
  274. ) {
  275. const link =
  276. "http://dabblet.com/gist/" + data.url.split("/").pop();
  277. const icon =
  278. "data:image/vnd.microsoft.icon;base64,AAABAAEAEBAAAAAAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAD///8B////AQAAAAMAAAAPAAAAHwAAACcAAAAfAAAADwAAAAP///8B////AQAAAAUAAAARAAAAHwAAAB0AAAAJ////AQAAAAcAAAAjqqqqb9vb28Xn5+fb29vbxaqqqm8AAAAjAAAABwAAAAkAAAApvLy8hd7e3snl5eXBAAAAIwAAAAMAAAAjzc3Nqf39/f/////////////////9/f3/0NDQqQAAACEAAAAp2NjYvf///////////////wAAADEAAAAPra2tc/39/f////////////b29vn///////////39/f8AAABFvLy8jf///////////f39/97e3r8AAAAhAAAAIdzc3Mf//////////66urp8AAABNrq6un///////////AAAAXePj49v//////Pz8/YqKin0AAAAlAAAACQAAACnq6urj//////Hx8fUAAABJAAAADQAAAEnv7+/z/////wAAAGXx8fHz/////+Tk5N8AAAAzAAAAA////wEAAAAh3d3dy///////////l5eXjQAAAEWXl5eN//////////8AAABp9fX19f/////g4ODVAAAAKf///wH///8BAAAAEbm5uYP///////////39/f/u7u7x/f39////////////AAAAafX19fX/////4ODg1QAAACn///8B////AQAAAAUAAAAn19fXu////////////////////////////////wAAAGn19fX1/////93d3dtoaGhXXFxcJwAAAAv///8BAAAABwAAACe5ubmF4+Pj1e/v7+nd3d3f8/Pz+f////8AAABp9fX19f/////c3Nzl7e3t5+zs7M0AAAAh////Af///wEAAAAFAAAAEwAAACUAAAAtAAAAU+np6ev/////AAAAafX19fX/////3Nzc5e3t7efs7OzNAAAAIf///wH///8B////Af///wH///8B////AQAAAC/r6+vn/////wAAAGn19fX1/////93d3dtpaWlVXFxcJwAAAAv///8B////Af///wH///8B////Af///wEAAAAh5ubm0/////8AAABd9fX18f/////i4uLLAAAAH////wH///8B////Af///wH///8B////Af///wH///8BAAAADXR0dEXs7Oy/AAAANbm5uXvz8/PjkpKSVQAAAA3///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAALAAAAFQAAAA0AAAAVAAAAHwAAAA////8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w==";
  279. menu.AddItem("Dabblet", link, link, icon, true);
  280. }
  281.  
  282. // Bl.ocks
  283. if (
  284. document.querySelector(
  285. '.file .file-actions a[href$="index.html" i], .file .file-actions a[href$="README.md" i]',
  286. )
  287. ) {
  288. const link = data.url.replace(
  289. "https://gist.github.com/",
  290. "https://bl.ocks.org/",
  291. );
  292. const icon =
  293. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAC0klEQVQ4jaWTTWhcZRSGn++7f3PnTqaTtrRJp4OVlmkzYbRRSQUJrkQoFEVw5UJQGRcVhO66KAxdihXdCFkWusrSIliIESuFRrASf2slY2xDaZN2Mpm5P3P/vq+LEAIprnyXh8Nzznl5D/xPid2Fq+120Yt7UypJjhzvRVe039tq9MrcrnjvGo69HDiVn8+02yGAuRtwaDhYeCZSp3ScobTCefY4ZBlxd52Tsb4stGZFbS4CLwPI3YDyvyvT9kiZ0uQU2BaDlTsMVjtgW5ROPIftjTDS+Xv663Nn6wBme7ZVDJLi1DBLjhTHzSvWXAdZrxP8eBOR5ux/5TUA+r//xODXW+RphCsNYRm6CGDGZnmhUi2citOEJIsRUmLt2YtoTBL+tkTQuQ1Ck/kh0pJIYYDYWVxuGhvTRbvIsYNHMaWFMLZ81UjciSbm4RpZt4u0JGLbc612AKlOxPOHX+Sx3yXTOYk06V/7ChBopSDP0VpvTQbSsE+YxXrebexrtWeLpiEMvEKJxqEm1T09Ft6qMHF9hdr1b/AqB3AnmximTTKMGEab3B09yPf1t0U6Wp031+8tmkJIsiwlyWIcy6FUq3F15hGFpZc4ff8G1RvfkivNA9dlvv46d8cmmTh6gGwjYLlvTZtCodcGD0Wuc/I8I85TlFYsiXFe+PAi1/68x2o3plEfxwNYXuOvzjrDOMV0CsJ0NrxX529+NyfKaqxZa+I5HqZhI6WgVHBoHKtSC2L+WffpBwlhnGIKgTQNpNyJsvj4s4/eC2z/C7tseForHi6/SeuNkzweREggTDJ++GUVlEYYAiEkvV709C+0Pm3tT/zED9SZ8PTMCaERqDxnmCoW/7iPZRlorQj8hHAQ6qcA2/rg/JczkXTncnvf2FRjnJJrc+vOGlGcMOiFuPnGI1cM3/lPwPZprQuz728mhc+1O+plKkeE/agk/QuXPzl7CeAJlkc5xMckqesAAAAASUVORK5CYII=";
  294. menu.AddItem("Bl.ocks", link, link, icon, true);
  295. }
  296. }
  297. }
  298.  
  299. // Init
  300. addMenu();
  301.  
  302. // Pjax
  303. document.addEventListener("pjax:end", addMenu);
  304. })();