crbug colorize

Colorize bug list based on status

当前为 2020-01-30 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name crbug colorize
  3. // @description Colorize bug list based on status
  4. // @match https://bugs.chromium.org/*
  5. // @version 1.0.3
  6. // @author wOxxOm
  7. // @namespace wOxxOm.scripts
  8. // @license MIT License
  9. // @run-at document-start
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. const sheet = new CSSStyleSheet();
  14. sheet.replaceSync(`
  15. .wOxxOm-Starred { font-weight: bold }
  16. .wOxxOm-Archived { color: gray }
  17. .wOxxOm-Assigned { color: #3f71b1 }
  18. .wOxxOm-Available { color: #92479a }
  19. .wOxxOm-Duplicate,
  20. .wOxxOm-Invalid { opacity: 0.3 }
  21. .wOxxOm-ExternalDependency { color: #ababab }
  22. .wOxxOm-Fixed { color: #227700 }
  23. .wOxxOm-Started,
  24. .wOxxOm-FixPending { color: #06908b }
  25. .wOxxOm-Unconfirmed,
  26. .wOxxOm-New { color: black }
  27. .wOxxOm-Untriaged { color: #947911 }
  28. .wOxxOm-Verified, .wOxxOm-Accepted { color: #6a846f }
  29. .wOxxOm-WontFix { color: #d00 }
  30. tr[class*="wOxxOm-"] td[width="100%"] a {
  31. color: inherit;
  32. text-decoration: underline;
  33. }
  34. `);
  35.  
  36. (async () => {
  37. const app = await added('mr-app');
  38. const main = await added('main', app);
  39. while (true) await colorize(main);
  40. })();
  41.  
  42. async function colorize(main) {
  43. const page = await added('mr-list-page', main);
  44. const list = await shadowOf(await added('mr-issue-list', page));
  45. const sheets = list.adoptedStyleSheets;
  46. if (!sheets.includes(sheet))
  47. list.adoptedStyleSheets = [...sheets, sheet];
  48. for (const el of list.querySelectorAll('td')) {
  49. const text = el.textContent.trim();
  50. switch (text) {
  51. case '':
  52. continue;
  53. case 'Accepted':
  54. case 'Archived':
  55. case 'Assigned':
  56. case 'Available':
  57. case 'Duplicate':
  58. case 'ExternalDependency':
  59. case 'FixPending':
  60. case 'Fixed':
  61. case 'Invalid':
  62. case 'New':
  63. case 'Started':
  64. case 'Unconfirmed':
  65. case 'Untriaged':
  66. case 'Verified':
  67. case 'WontFix':
  68. el.parentNode.classList.add('wOxxOm-' + text);
  69. continue;
  70. case '★':
  71. el.parentNode.classList.add('wOxxOm-Starred');
  72. continue;
  73. }
  74. if (el.align === 'right' && (text === '1' || text === '0')) {
  75. el.textContent = '';
  76. }
  77. if (/% regression in|\b\d(\.\d)?%(-\d(\.\d)?%)? improvement in|test.*?is flaky|^(Android|Chrome)$/.test(text) && el.parentNode) {
  78. el.parentNode.remove();
  79. }
  80. }
  81. await removed(page);
  82. }
  83.  
  84. async function added(sel, parent = document.documentElement) {
  85. const target =
  86. parent.shadowRoot ||
  87. !parent.localName.includes('-') && parent ||
  88. await shadowOf(parent);
  89. return target.querySelector(sel) || new Promise(resolve => {
  90. const mo = new MutationObserver(() => {
  91. const el = target.querySelector(sel);
  92. if (el) {
  93. mo.disconnect();
  94. resolve(el);
  95. }
  96. });
  97. mo.observe(target, {childList: true, subtree: true});
  98. });
  99. }
  100.  
  101. function removed(el) {
  102. const root = el.getRootNode();
  103. return root.contains(el) && new Promise(resolve => {
  104. const mo = new MutationObserver(() => {
  105. if (!root.contains(el)) {
  106. mo.disconnect();
  107. resolve();
  108. }
  109. });
  110. mo.observe(root, {childList: true, subtree: true});
  111. });
  112. }
  113.  
  114. function shadowOf(el) {
  115. return el.shadowRoot || new Promise(resolve => {
  116. el.attachShadow = function (...args) {
  117. delete el.attachShadow;
  118. const root = el.attachShadow(...args);
  119. resolve(root);
  120. return root;
  121. };
  122. });
  123. }