🏠 Home 

github-file-icon

change github file icon


Installer dette script?
  1. // ==UserScript==
  2. // @name github-file-icon
  3. // @namespace github-file-icon
  4. // @description change github file icon
  5. // @version 1.0.0
  6. // @author roojay <roojay520@gmail.com>
  7. // @homepage https://github.com/roojay520/github-file-icon
  8. // @license MIT
  9. // @include https://github.com/*
  10. // @run-at document-start
  11. // @require https://cdn.jsdelivr.net/npm/file-icons-js@1.0.3/index.min.js
  12. // @noframes
  13. // @connect *
  14. // ==/UserScript==
  15. (function (FileIcons) {
  16. 'use strict';
  17. FileIcons = FileIcons && Object.prototype.hasOwnProperty.call(FileIcons, 'default') ? FileIcons['default'] : FileIcons;
  18. const hasLoaded = () => document.readyState === 'interactive' || document.readyState === 'complete';
  19. const domLoaded = new Promise(resolve => {
  20. if (hasLoaded()) {
  21. resolve();
  22. } else {
  23. document.addEventListener('DOMContentLoaded', () => {
  24. resolve();
  25. }, {
  26. capture: true,
  27. once: true,
  28. passive: true
  29. });
  30. }
  31. });
  32. Object.defineProperty(domLoaded, 'hasLoaded', {
  33. get: () => hasLoaded()
  34. });
  35. var domLoaded_1 = domLoaded;
  36. // Types inspired by
  37. // https://github.com/Microsoft/TypeScript/blob/9d3707d/src/lib/dom.generated.d.ts#L10581
  38. // Type predicate for TypeScript
  39. function isQueryable(object) {
  40. return typeof object.querySelectorAll === 'function';
  41. }
  42. function select(selectors, baseElement) {
  43. // Shortcut with specified-but-null baseElement
  44. if (arguments.length === 2 && !baseElement) {
  45. return null;
  46. }
  47. return (baseElement !== null && baseElement !== void 0 ? baseElement : document).querySelector(String(selectors));
  48. }
  49. function selectLast(selectors, baseElement) {
  50. // Shortcut with specified-but-null baseElement
  51. if (arguments.length === 2 && !baseElement) {
  52. return null;
  53. }
  54. const all = (baseElement !== null && baseElement !== void 0 ? baseElement : document).querySelectorAll(String(selectors));
  55. return all[all.length - 1];
  56. }
  57. /**
  58. * @param selectors One or more CSS selectors separated by commas
  59. * @param [baseElement] The element to look inside of
  60. * @return Whether it's been found
  61. */
  62. function selectExists(selectors, baseElement) {
  63. if (arguments.length === 2) {
  64. return Boolean(select(selectors, baseElement));
  65. }
  66. return Boolean(select(selectors));
  67. }
  68. function selectAll(selectors, baseElements) {
  69. // Shortcut with specified-but-null baseElements
  70. if (arguments.length === 2 && !baseElements) {
  71. return [];
  72. }
  73. // Can be: select.all('selectors') or select.all('selectors', singleElementOrDocument)
  74. if (!baseElements || isQueryable(baseElements)) {
  75. const elements = (baseElements !== null && baseElements !== void 0 ? baseElements : document).querySelectorAll(String(selectors));
  76. return Array.apply(null, elements);
  77. }
  78. const all = [];
  79. for (let i = 0; i < baseElements.length; i++) {
  80. const current = baseElements[i].querySelectorAll(String(selectors));
  81. for (let ii = 0; ii < current.length; ii++) {
  82. all.push(current[ii]);
  83. }
  84. }
  85. // Preserves IE11 support and performs 3x better than `...all` in Safari
  86. const array = [];
  87. all.forEach(function (v) {
  88. array.push(v);
  89. });
  90. return array;
  91. }
  92. select.last = selectLast;
  93. select.exists = selectExists;
  94. select.all = selectAll;
  95. var __async = (__this, __arguments, generator) => {
  96. return new Promise((resolve, reject) => {
  97. var fulfilled = (value) => {
  98. try {
  99. step(generator.next(value));
  100. } catch (e) {
  101. reject(e);
  102. }
  103. };
  104. var rejected = (value) => {
  105. try {
  106. step(generator.throw(value));
  107. } catch (e) {
  108. reject(e);
  109. }
  110. };
  111. var step = (r###lt) => {
  112. return r###lt.done ? resolve(r###lt.value) : Promise.resolve(r###lt.value).then(fulfilled, rejected);
  113. };
  114. step((generator = generator.apply(__this, __arguments)).next());
  115. });
  116. };
  117. const FILE_NAME_SELECTOR = 'div.js-navigation-item > div[role="rowheader"] > span';
  118. const FILE_ICON_SELECTOR = 'div.js-navigation-item > div[role="gridcell"]:first-child';
  119. const FILE_LIST_WRAPPER = ".repository-content .Box.mb-3";
  120. const update = () => {
  121. const filenameDoms = select.all(FILE_NAME_SELECTOR);
  122. const iconDoms = select.all(FILE_ICON_SELECTOR);
  123. for (let i = 0; i < filenameDoms.length; i += 1) {
  124. const filename = filenameDoms[i].innerText.trim();
  125. const iconDom = iconDoms[i].querySelector(".octicon");
  126. const isDirectory = iconDom.classList.contains("octicon-file-directory");
  127. const className = FileIcons.getClassWithColor(filename);
  128. if (className && !isDirectory) {
  129. const icon = document.createElement("span");
  130. icon.className = `icon octicon ${className}`;
  131. iconDom.parentNode.replaceChild(icon, iconDom);
  132. }
  133. }
  134. };
  135. const observer = new MutationObserver(update);
  136. const observeFragment = () => {
  137. const ajaxFiles = select(FILE_LIST_WRAPPER);
  138. if (ajaxFiles) {
  139. observer.observe(ajaxFiles, {
  140. childList: true
  141. });
  142. }
  143. };
  144. const init = () => __async(undefined, [], function* () {
  145. observeFragment();
  146. yield domLoaded_1;
  147. update();
  148. document.addEventListener("pjax:end", update);
  149. document.addEventListener("pjax:end", observeFragment);
  150. });
  151. init();
  152. }(FileIcons));