GitHub Code Guides

A userscript that allows you to add one or more vertical guidelines to the code

Fra 14.04.2017. Se den seneste versjonen.

  1. // ==UserScript==
  2. // @name GitHub Code Guides
  3. // @version 1.1.5
  4. // @description A userscript that allows you to add one or more vertical guidelines to the code
  5. // @license https://creativecommons.org/licenses/by-sa/4.0/
  6. // @author Rob Garrison
  7. // @namespace https://github.com/Mottie
  8. // @include https://github.com/*
  9. // @run-at document-idle
  10. // @grant GM_getValue
  11. // @grant GM_setValue
  12. // @grant GM_registerMenuCommand
  13. // @icon https://github.com/fluidicon.png
  14. // ==/UserScript==
  15. /* copy into textarea to check the guides
  16. 1 2 3 4 5 6 7 8
  17. 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345
  18. */
  19. (() => {
  20. "use strict";
  21. const style = document.createElement("style");
  22. // eslint-disable-next-line one-var
  23. let guides = GM_getValue("ghcg-guides", [{
  24. chars: 80,
  25. color: "rgba(0, 0, 0, .3)",
  26. width: 0.2
  27. }]),
  28. font = GM_getValue("ghcg-font", "Menlo"),
  29. tabSize = GM_getValue("ghcg-tabs", 2);
  30.  
  31. function adjust(val) {
  32. return `calc(13px + ${val.toFixed(1)}ch)`;
  33. }
  34.  
  35. function addDefinition(start, end, color) {
  36. return `
  37. transparent ${start},
  38. ${color} ${start},
  39. ${color} ${end},
  40. transparent ${end},
  41. `;
  42. }
  43.  
  44. function addGuides(vals) {
  45. let css = "",
  46. diff = "";
  47. // to align the guides *after* the setting, we need to add 1, then add
  48. // another 0.1 to give the guide a tiny bit of white space to the left
  49. vals.forEach(guide => {
  50. let start = parseFloat(guide.chars),
  51. size = parseFloat(guide.width) || 0.2;
  52. const color = guide.color || "rgba(0, 0, 0, .3)";
  53. // each line needs to be at least 0.2ch in width to be visible
  54. size = size > 0.2 ? size : 0.2;
  55. css += addDefinition(adjust(start), adjust(start + size), color);
  56.  
  57. // shift start to the left 1ch for diff block alignment
  58. start += 1;
  59. diff += addDefinition(adjust(start), adjust(start + size), color);
  60. });
  61. style.textContent = `
  62. table.tab-size[data-tab-size] {
  63. tab-size: ${tabSize};
  64. }
  65. /* repo file view uses padding-left: 10px */
  66. table:not(.diff-table) .blob-code,
  67. table.diff-table tr.blob-expanded .blob-code,
  68. .blob-code span.blob-code-inner {
  69. padding-left: 13px;
  70. }
  71. table.diff-table .blob-code {
  72. padding-left: 0;
  73. }
  74. .blob-code-context .blob-code-inner,
  75. .blob-code-addition .blob-code-inner,
  76. .blob-code-deletion .blob-code-inner {
  77. background: linear-gradient(to right, transparent 0%, ${diff} transparent 100%) !important;
  78. }
  79. .blob-code span.blob-code-inner {
  80. display: block !important;
  81. }
  82. span.blob-code-inner, td.blob-code-inner:not(.blob-code-hunk) {
  83. font-family: "${font}", Consolas, "Liberation Mono", Menlo, Courier, monospace !important;
  84. background: linear-gradient(to right, transparent 0%, ${css} transparent 100%) !important;
  85. }
  86. `;
  87. }
  88.  
  89. function validateGuides(vals) {
  90. let last = 0;
  91. const valid = [];
  92. if (!Array.isArray(vals)) {
  93. console.log("Code-Guides Userscript: Invalid guidelines", vals);
  94. return;
  95. }
  96. // Object.keys() creates an array of string values
  97. const lines = vals.sort((a, b) => parseFloat(a.chars) - parseFloat(b.chars));
  98. lines.forEach(line => {
  99. const num = parseFloat(line.chars);
  100. // 0.2 is the width of the "ch" in CSS to make it visible
  101. if (num >= last + line.width) {
  102. valid.push(line);
  103. last = num;
  104. }
  105. });
  106. if (valid.length) {
  107. guides = valid;
  108. GM_setValue("ghcg-guides", valid);
  109. GM_setValue("ghcg-font", font);
  110. GM_setValue("ghcg-tabs", tabSize);
  111. addGuides(valid);
  112. }
  113. }
  114.  
  115. document.querySelector("head").appendChild(style);
  116. validateGuides(guides);
  117.  
  118. // Add GM options
  119. GM_registerMenuCommand("Set code guideline position & color", () => {
  120. let val = prompt(
  121. `Enter valid JSON [{ "chars":80, "color":"#f00", "width":0.2 }, ...}]`,
  122. JSON.stringify(guides)
  123. );
  124. if (val !== null) {
  125. try {
  126. val = JSON.parse(val);
  127. validateGuides(val);
  128. } catch (err) {
  129. console.log(err);
  130. }
  131. }
  132. });
  133.  
  134. GM_registerMenuCommand("Set code guideline default font", () => {
  135. const val = prompt("Enter code font (monospaced)", font);
  136. if (val !== null) {
  137. font = val;
  138. validateGuides(guides);
  139. }
  140. });
  141.  
  142. GM_registerMenuCommand("Set code guideline tab size", () => {
  143. const val = prompt("Enter code guideline tab size", tabSize);
  144. if (val !== null) {
  145. tabSize = val;
  146. validateGuides(guides);
  147. }
  148. });
  149.  
  150. })();