GitHub Code Colors

A userscript that adds a color swatch next to the code color definition

目前为 2017-04-24 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name GitHub Code Colors
  3. // @version 1.1.7
  4. // @description A userscript that adds a color swatch next to the code color definition
  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_addStyle
  11. // @require https://greasyfork.org/scripts/28721-mutations/code/mutations.js?version=189706
  12. // @icon https://github.com/fluidicon.png
  13. // ==/UserScript==
  14. (() => {
  15. "use strict";
  16.  
  17. GM_addStyle(`
  18. .ghcc-block { width:12px; height:12px; display:inline-block;
  19. vertical-align:middle; margin-right:4px; border:1px solid #555; }
  20. `);
  21.  
  22. const namedColors = [
  23. "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
  24. "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
  25. "burlywood", "cadetblue", "chartreuse", "chocolate", "coral",
  26. "cornflowerblue", "cornsilk", "crimson", "cyan", "darkblue", "darkcyan",
  27. "darkgoldenrod", "darkgray", "darkgrey", "darkgreen", "darkkhaki",
  28. "darkmagenta", "darkolivegreen", "darkorange", "darkorchid", "darkred",
  29. "darksalmon", "darkseagreen", "darkslateblue", "darkslategray",
  30. "darkslategrey", "darkturquoise", "darkviolet", "deeppink", "deepskyblue",
  31. "dimgray", "dimgrey", "dodgerblue", "firebrick", "floralwhite",
  32. "forestgreen", "fuchsia", "gainsboro", "ghostwhite", "gold", "goldenrod",
  33. "gray", "grey", "green", "greenyellow", "honeydew", "hotpink",
  34. "indianred", "indigo", "ivory", "khaki", "lavender", "lavenderblush",
  35. "lawngreen", "lemonchiffon", "lightblue", "lightcoral", "lightcyan",
  36. "lightgoldenrodyellow", "lightgray", "lightgrey", "lightgreen",
  37. "lightpink", "lightsalmon", "lightseagreen", "lightskyblue",
  38. "lightslategray", "lightslategrey", "lightsteelblue", "lightyellow",
  39. "lime", "limegreen", "linen", "magenta", "maroon", "mediumaquamarine",
  40. "mediumblue", "mediumorchid", "mediumpurple", "mediumseagreen",
  41. "mediumslateblue", "mediumspringgreen", "mediumturquoise",
  42. "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
  43. "navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange",
  44. "orangered", "orchid", "palegoldenrod", "palegreen", "paleturquoise",
  45. "palevioletred", "papayawhip", "peachpuff", "peru", "pink", "plum",
  46. "powderblue", "purple", "rebeccapurple", "red", "rosybrown", "royalblue",
  47. "saddlebrown", "salmon", "sandybrown", "seagreen", "seashell", "sienna",
  48. "silver", "skyblue", "slateblue", "slategray", "slategrey", "snow",
  49. "springgreen", "steelblue", "tan", "teal", "thistle", "tomato",
  50. "turquoise", "violet", "wheat", "white", "whitesmoke", "yellow",
  51. "yellowgreen"
  52. ].join("|"),
  53.  
  54. // don't use a div, because GitHub-Dark adds a :hover background
  55. // color definition on divs
  56. block = document.createElement("span");
  57. block.className = "ghcc-block";
  58.  
  59. function addNode(el, val) {
  60. const node = block.cloneNode();
  61. node.style.backgroundColor = val;
  62. // don't add node if color is invalid
  63. if (node.style.backgroundColor !== "") {
  64. el.insertBefore(node, el.childNodes[0]);
  65. }
  66. }
  67.  
  68. function addColors() {
  69. if (document.querySelector(".highlight")) {
  70. let indx = 0;
  71. const regexNamed = new RegExp("^(" + namedColors + ")$", "i"),
  72. // #123, #123456 or 0x123456 (unix style colors, used by three.js)
  73. regexHex = /^(#|0x)([0-9A-F]{6,8}|[0-9A-F]{3,4})$/i,
  74. // rgb(0,0,0) or rgba(0,0,0,0.2)
  75. regexRGB = /^rgba?(\([^\)]+\))?/i,
  76. regexRGBA = /rgba/i,
  77. // hsl(0,0%,0%) or hsla(0,0%,0%,0.2);
  78. regexHSL = /^hsla?(\([^\)]+\))?/i,
  79.  
  80. // misc regex
  81. regexQuotes = /['"]/g,
  82. regexUnix = /^0x/,
  83. regexPercent = /%%/g,
  84.  
  85. // .pl-c1 targets css hex colors, "rgb" and "hsl"
  86. els = document.querySelectorAll(".pl-c1, .pl-s"),
  87. len = els.length;
  88.  
  89. // loop with delay to allow user interaction
  90. const loop = () => {
  91. let el, txt, tmp, indx2,
  92. // max number of DOM insertions per loop
  93. max = 0;
  94. while (max < 20 && indx < len) {
  95. if (indx >= len) {
  96. return;
  97. }
  98. el = els[indx];
  99. txt = el.textContent;
  100. if (el.classList.contains("pl-s")) {
  101. txt = txt.replace(regexQuotes, "");
  102. }
  103. if (regexHex.test(txt) || regexNamed.test(txt)) {
  104. if (!el.querySelector(".ghcc-block")) {
  105. addNode(el, txt.replace(regexUnix, "#"));
  106. max++;
  107. }
  108. } else if (regexRGB.test(txt)) {
  109. if (!el.querySelector(".ghcc-block")) {
  110. // color in a string contains everything
  111. if (el.classList.contains("pl-s")) {
  112. txt = txt.match(regexRGB)[0];
  113. } else {
  114. // rgb(a) colors contained in multiple "pl-c1" spans
  115. indx2 = regexRGBA.test(txt) ? 4 : 3;
  116. tmp = [];
  117. while (indx2) {
  118. tmp.push(els[++indx].textContent);
  119. indx2--;
  120. }
  121. txt += "(" + tmp.join(",") + ")";
  122. }
  123. addNode(el, txt);
  124. max++;
  125. }
  126. } else if (regexHSL.test(txt)) {
  127. if (!el.querySelector(".ghcc-block")) {
  128. tmp = /a$/i.test(txt);
  129. txt = el.classList.contains("pl-s") ?
  130. // color in a string contains everything
  131. txt.match(regexHSL)[0] :
  132. // traverse this HTML... & els only contains the pl-c1 nodes
  133. // <span class="pl-c1">hsl</span>(<span class="pl-c1">1</span>,
  134. // <span class="pl-c1">1</span><span class="pl-k">%</span>,
  135. // <span class="pl-c1">1</span><span class="pl-k">%</span>);
  136. txt + "(" + els[++indx].textContent + "," +
  137. els[++indx].textContent + "%," +
  138. // hsla needs one more parameter
  139. els[++indx].textContent + "%" +
  140. (tmp ? "," + els[++indx].textContent : "") + ")";
  141. // sometimes (previews only?) the .pl-k span is nested inside
  142. // the .pl-c1 span, so we end up with "%%"
  143. addNode(el, txt.replace(regexPercent, "%"));
  144. max++;
  145. }
  146. }
  147. indx++;
  148. }
  149. if (indx < len) {
  150. setTimeout(() => {
  151. loop();
  152. }, 200);
  153. }
  154. };
  155. loop();
  156. }
  157. }
  158.  
  159. document.addEventListener("ghmo:container", addColors);
  160. document.addEventListener("ghmo:preview", addColors);
  161. addColors();
  162.  
  163. })();