GitHub - Make PRs easier to diff

Add some js buttons to diffs

2016-01-29 يوللانغان نەشرى. ئەڭ يېڭى نەشرىنى كۆرۈش.

  1. // ==UserScript==
  2. // @name GitHub - Make PRs easier to diff
  3. // @namespace https://github.com/drKnoxy/
  4. // @version 1.1
  5. // @description Add some js buttons to diffs
  6. // @author DrKnoxy
  7. // @include https://github.com/*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. /**
  12. * Internal Application Logic
  13. */
  14. var tool = (function() {
  15. // Globals and exports
  16. ////////////////////////////////////
  17.  
  18. // Prep global variables
  19. var isWhitespaceVisible = _isWhitespaceVisible();
  20.  
  21. /**
  22. * The collapse headers feature
  23. */
  24. var collapse = (function(){
  25. var toggleId = 'js-blob-toggle';
  26. var blobSelector = '.blob-wrapper, .render-wrapper, .file-header + .empty';
  27. var isAllVisible = true;
  28. return {
  29. addElement: addElement,
  30. monitor: monitor
  31. };
  32.  
  33. //////////////////////
  34.  
  35. function monitor() {
  36. _monitorHeader();
  37. _monitorToggle();
  38. }
  39.  
  40. function _monitorHeader() {
  41. $(document).on('click', '.file-header', function(e) {
  42. $(this).next(blobSelector).toggle();
  43. });
  44. }
  45.  
  46. function _monitorToggle() {
  47. $(document).on('click', '#' + toggleId, function(e) {
  48. e.preventDefault();
  49.  
  50. // can't use toggle, because we need to obey our state
  51. // not the items state
  52. if (isAllVisible) {
  53. $(this).addClass('selected');
  54. $(blobSelector).hide();
  55. } else {
  56. $(this).removeClass('selected');
  57. $(blobSelector).show();
  58. }
  59.  
  60. isAllVisible = !isAllVisible;
  61. });
  62. }
  63.  
  64. function addElement() {
  65. var toggle = {
  66. id: toggleId,
  67. label: 'Collapse'
  68. };
  69.  
  70. _addToggle(toggle);
  71. }
  72.  
  73. })();
  74.  
  75. /**
  76. * The hide whitespace features
  77. */
  78. var whitespace = (function(isWhitespaceVisible){
  79. var toggleId = 'js-whitespace-toggle';
  80. var isWhitespaceVisible = isWhitespaceVisible;
  81.  
  82. return {
  83. addElement: addElement,
  84. monitor: monitor
  85. };
  86.  
  87. //////////////////////
  88.  
  89. function monitor() {
  90. $(document).on('click', '#' + toggleId, function(e) {
  91. e.preventDefault();
  92.  
  93. // blow away the whole search query...
  94. window.location.search = isWhitespaceVisible ? '' : 'w=1';
  95. });
  96. }
  97.  
  98. function addElement() {
  99. var toggle = {
  100. id: toggleId,
  101. label: 'Ignore Whitespace',
  102. isSelected: isWhitespaceVisible
  103. };
  104.  
  105. _addToggle(toggle);
  106. }
  107.  
  108. })(isWhitespaceVisible);
  109.  
  110. var betterTextarea = (function(){
  111. var tabInsertCharacter = " ";
  112.  
  113. return {
  114. init: init
  115. };
  116.  
  117. //////////////////////////
  118.  
  119. function init() {
  120. useTabForIndenting();
  121. }
  122.  
  123. function useTabForIndenting() {
  124. $(document).on('keydown', 'textarea', function(e) {
  125. // tab was pressed
  126. if (e.keyCode === 9) {
  127. // get caret position/selection
  128. var start = this.selectionStart;
  129. var end = this.selectionEnd;
  130.  
  131. var $this = $(this);
  132. var value = $this.val();
  133.  
  134. var newVal = [
  135. value.substring(0, start),
  136. tabInsertCharacter,
  137. value.substring(end)
  138. ].join('');
  139.  
  140. $this.val(newVal);
  141.  
  142. // put caret at right position
  143. this.selectionStart = this.selectionEnd = start + tabInsertCharacter.length;
  144.  
  145. // prevent the focus loss
  146. e.preventDefault();
  147. }
  148. });
  149. }
  150.  
  151. })();
  152.  
  153. /**
  154. * Public methods
  155. */
  156. return {
  157. init: init,
  158. addElements: addElements
  159. }
  160.  
  161. // Implementation logic
  162. /////////////////////
  163.  
  164. /**
  165. * call me once
  166. */
  167. function init() {
  168. // Watch for events
  169. collapse.monitor();
  170. whitespace.monitor();
  171. betterTextarea.init();
  172. }
  173.  
  174. /**
  175. * call me on pjax route change,
  176. * or if you are nervous that ajax happened
  177. */
  178. function addElements() {
  179. collapse.addElement();
  180. whitespace.addElement();
  181. }
  182.  
  183. /**
  184. * Add a button to the page
  185. * @param options {id, label, isSelected}
  186. */
  187. function _addToggle(options) {
  188. var toggleTemplate = '<a id="{{id}}" class="{{cssClass}}" style="margin-left: 4px;">{{label}}</a>';
  189.  
  190. // Make sure it isn't on the page already
  191. if (!$('#' + options.id).length) {
  192. options.cssClass = 'btn btn-sm right';
  193. if (options.isSelected) {
  194. options.cssClass += ' selected';
  195. }
  196. tmpl = _render(toggleTemplate, options);
  197.  
  198. $('#toc .btn-group').before(tmpl);
  199. }
  200. }
  201.  
  202. function _isWhitespaceVisible() {
  203. var search = _getSearchObject();
  204. return (search.w && parseInt(search.w, 10) == 1);
  205.  
  206. function _getSearchObject() {
  207. var search = {};
  208. if (window.location.search) {
  209. window.location.search.replace('?', '').split('&').forEach(function(el) {
  210. var group = el.split('=');
  211. var prop = group[0];
  212. var val = group[1] || '';
  213. search[prop] = val;
  214. });
  215. }
  216.  
  217. return search;
  218. }
  219. }
  220.  
  221. /**
  222. * Simple template rendering
  223. * double curly brace syntax {{id}} or {{ id }}
  224. *
  225. * @param {string} tmpl
  226. * @param {obj} data [description]
  227. * @return {string}
  228. */
  229. function _render(tmpl, data) {
  230. var curlyBraceRegex = /{{([^}}]+)}}/g
  231. var finds = tmpl.match(curlyBraceRegex);
  232.  
  233. finds.forEach(function(curlyProp) {
  234. var prop = curlyProp.replace('{{', '').replace('}}','').trim();
  235.  
  236. if (data[prop]){
  237. tmpl = tmpl.split(curlyProp).join(data[prop]);
  238. }
  239. });
  240.  
  241. return tmpl;
  242. }
  243.  
  244. })();
  245.  
  246. /**
  247. * Applying our tool to github
  248. */
  249. $(function() {
  250.  
  251. tool.init();
  252. tool.addElements();
  253.  
  254. // Add elements on page change
  255. $(document).on('pjax:complete pjax:popstate', function(e) {
  256. tool.addElements();
  257. });
  258. });
  259.