GitHub Label Color Picker

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

当前为 2020-09-08 提交的版本,查看 最新版本

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