GitHub Label Color Picker

A userscript that adds a color picker to the label color input

当前为 2018-05-16 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name GitHub Label Color Picker
  3. // @version 1.0.5
  4. // @description A userscript that adds a color picker to the label color input
  5. // @license MIT
  6. // @author Rob Garrison
  7. // @contributor darkred
  8. // @namespace https://github.com/Mottie
  9. // @include https://github.com/*
  10. // @run-at document-idle
  11. // @grant GM_addStyle
  12. // @grant GM_getValue
  13. // @grant GM_setValue
  14. // @grant GM_registerMenuCommand
  15. // @require https://greasyfork.org/scripts/23181-colorpicker/code/colorPicker.js?version=147862
  16. // @icon https://assets-cdn.github.com/pinned-octocat.svg
  17. // ==/UserScript==
  18. (() => {
  19. "use strict";
  20.  
  21. // GitHub-Dark changes "text-black" to #c0c0c0
  22. GM_addStyle(`
  23. div.cp-app { margin-top:110px; margin-left:-8px; z-index:10; }
  24. .js-new-label-color-icon { pointer-events:none; }
  25. .js-new-label-color-icon.text-black { color:#000 !important; }
  26. `);
  27.  
  28. function addPicker() {
  29. if ($(".js-new-label-color")) {
  30. jsColorPicker(".js-new-label-color-input", {
  31. customBG: "#222",
  32. noAlpha: true,
  33. renderCallback: function(colors) {
  34. let input = this && this.input;
  35. if (input) {
  36. updateSwatch(input, colors);
  37. }
  38. }
  39. });
  40. }
  41. }
  42.  
  43. function updateSwatch(input, colors) {
  44. let background = "#" + colors.HEX;
  45. input.value = background;
  46. let textColor = calcContrast(colors.HEX);
  47. // Update color swatch next to input
  48. let swatch = $(".js-new-label-color", input.closest("dd"));
  49. updateIcon(swatch, textColor);
  50. updateColors(swatch, background, textColor);
  51. // Update label preview
  52. swatch = $(
  53. ".js-label-preview .IssueLabel--big",
  54. input.closest(".table-list-item")
  55. );
  56. updateColors(swatch, background, textColor);
  57. }
  58.  
  59. function updateIcon(swatch, textColor) {
  60. let icon = $(".octicon", swatch);
  61. // !important set on these GitHub primer color definitions
  62. icon.classList.remove("text-white", "text-black");
  63. icon.classList.add("text-" + textColor);
  64. }
  65.  
  66. function updateColors(el, background, color) {
  67. el.style.backgroundColor = background;
  68. el.style.color = color;
  69. }
  70.  
  71. /* replace colorPicker storage */
  72. window.ColorPicker.docCookies = (key, val) => {
  73. if (typeof val === "undefined") {
  74. return GM_getValue(key);
  75. }
  76. GM_setValue(key, val);
  77. };
  78.  
  79. /* colorPickerMemosNoAlpha *MUST* follow this format
  80. "'rgba(83,25,231,1)','rgba(86,66,66,1)','rgba(22,20,223,1)'"
  81. */
  82. function convertColorsToRgba(values) {
  83. let result = [];
  84. // see http://stackoverflow.com/a/26196012/145346
  85. values
  86. .replace(/['"]/g, "")
  87. .split(/\s*,(?![^()]*(?:\([^()]*\))?\))\s*/g)
  88. .forEach(val => {
  89. let rgb = hexToRgb(val);
  90. if (rgb) {
  91. result.push(`'rgba(${rgb.r},${rgb.g},${rgb.b},1)'`);
  92. } else if (rgb === null && val.indexOf("rgba(") > -1) {
  93. // allow adding rgba() definitions
  94. result.push(`'${val}'`);
  95. }
  96. });
  97. return result.join(",");
  98. }
  99.  
  100. // Modified code from http://stackoverflow.com/a/5624139/145346
  101. function hexToRgb(hex) {
  102. let result,
  103. // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
  104. shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
  105. hex = hex.replace(shorthandRegex, (m, r, g, b) => {
  106. return r + r + g + g + b + b;
  107. });
  108. result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  109. return result ? {
  110. r: parseInt(result[1], 16),
  111. g: parseInt(result[2], 16),
  112. b: parseInt(result[3], 16)
  113. } : null;
  114. }
  115.  
  116. // Calculate contrasting text color for the given background color
  117. // https://24ways.org/2010/calculating-color-contrast/
  118. function calcContrast(hex) {
  119. const r = parseInt(hex.substr(0, 2), 16),
  120. g = parseInt(hex.substr(2, 2), 16),
  121. b = parseInt(hex.substr(4, 2), 16),
  122. yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
  123. return yiq >= 128 ? "black" : "white";
  124. }
  125.  
  126. function $(selector, el) {
  127. return (el || document).querySelector(selector);
  128. }
  129.  
  130. // Add GM options
  131. GM_registerMenuCommand(
  132. "Set label ColorPicker swatches (8 HEX or RGBA Max)",
  133. () => {
  134. const colors = GM_getValue("colorPickerMemosNoAlpha", "#000000,#ffffff"),
  135. val = prompt("Set label default colors (8 max):", colors);
  136. if (val !== null && typeof val === "string") {
  137. GM_setValue("colorPickerMemosNoAlpha", convertColorsToRgba(val));
  138. }
  139. }
  140. );
  141.  
  142. document.body.addEventListener("click", event => {
  143. // initialize if "Edit" or "New label" button clicked
  144. // because "Save changes" updates the entire item
  145. if (
  146. event.target && event.target.matches(".js-edit-label, .js-details-target")
  147. ) {
  148. addPicker();
  149. }
  150. });
  151. addPicker();
  152.  
  153. })();