Dev stuff

7/29/2024, 8:57:58 PM

当前为 2024-07-30 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/502146/1419173/Dev%20stuff.js

  1. // ==UserScript==
  2. // @name Dev stuff
  3. // @namespace Violentmonkey Scripts
  4. // @match https://*/*
  5. // @grant none
  6. // @version 0.1
  7. // @author Shaun Mitchell <shaun@shitchell.com>
  8. // @description 7/29/2024, 8:57:58 PM
  9. // @license WTFPL
  10. // ==/UserScript==
  11.  
  12. function mapToStyle(styles) {
  13. return Object.entries(styles)
  14. .map(([key, value]) => `${key}: ${value};`)
  15. .join(' ');
  16. }
  17.  
  18. class Debugger {
  19. static name = "debugger";
  20. static level = "debug";
  21. static levels = ["debug", "info", "warn", "error"];
  22. static styles = {
  23. debug: {
  24. "color": "grey",
  25. },
  26. info: {
  27. "color": "cyan"
  28. },
  29. warn: {
  30. "color": "yellow",
  31. "font-weight": "bold"
  32. },
  33. error: {
  34. "background-color": "red",
  35. "color": "black",
  36. "font-weight": "bold",
  37. "font-size": "1.1em"
  38. }
  39. }
  40.  
  41. static setLevel(level) {
  42. this.level = level;
  43. }
  44.  
  45. static isValidLevel(level) {
  46. let cur_index = -1;
  47. let lvl_index = -1;
  48.  
  49. for (let i = 0; i < this.levels.length; i++) {
  50. let l = this.levels[i];
  51. if (l == this.level) {
  52. cur_index = i;
  53. }
  54. if (l == level) {
  55. lvl_index = i;
  56. }
  57. if (cur_index > -1 && lvl_index > -1) {
  58. break;
  59. }
  60. }
  61.  
  62. return lvl_index >= cur_index;
  63. }
  64.  
  65. static log(level, ...args) {
  66. if (this.isValidLevel(level)) {
  67. const timestamp = new Date().toISOString().replace("T", " ").replace(/\..*/, "")
  68. const style = mapToStyle(this.styles[level]);
  69. console[level](`%c[${this.name}.${level} | ${timestamp}]`, style, ...args);
  70. }
  71. }
  72.  
  73. static debug(...args) { this.log("debug", ...args) }
  74. static info(...args) { this.log("info", ...args) }
  75. static warn(...args) { this.log("warn", ...args) }
  76. static error(...args) { this.log("error", ...args) }
  77. }
  78.  
  79. function debug(...args) { Debugger.debug(...args) }
  80. function info(...args) { Debugger.info(...args) }
  81. function warn(...args) { Debugger.warn(...args) }
  82. function error(...args) { Debugger.error(...args) }
  83.  
  84. // attribution:
  85. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value
  86. function getCircularReplacer() {
  87. const ancestors = [];
  88. let i = 0;
  89.  
  90. return function(key, value) {
  91. if (i % 100 === 99) {
  92. Debugger.debug("processing key", key);
  93. }
  94. if (typeof value !== "object" || value === null) {
  95. return value;
  96. }
  97.  
  98. // `this` is the object that value is contained in,
  99. // i.e., its direct parent.
  100. while (ancestors.length > 0 && ancestors.at(-1) !== this) {
  101. ancestors.pop();
  102. }
  103.  
  104. if (ancestors.includes(value)) {
  105. return "[Circular]";
  106. }
  107.  
  108. ancestors.push(value);
  109. return value;
  110. };
  111. }
  112.  
  113. function downloadObjectJSON(object, filename, indent) {
  114. const default_filename = "object-blob.js.json";
  115. const default_indent = 4;
  116.  
  117. // Allow for intelligent argument parsing for, e.g.: `downloadObjectBlob(foo, indent=4)`
  118. args = [object, filename, indent];
  119. filename = undefined;
  120. indent = undefined;
  121. for (const arg of args) {
  122. switch (typeof arg) {
  123. case 'number':
  124. indent = arg;
  125. break;
  126. case 'string':
  127. filename = arg;
  128. break;
  129. case 'object':
  130. object = arg;
  131. break;
  132. case 'undefined':
  133. break;
  134. default:
  135. error(`error: unexpected type for ${arg}`);
  136. return null
  137. }
  138. }
  139. if (filename === undefined) { filename = default_filename }
  140. if (indent === undefined) { indent = default_indent }
  141. blob = new Blob([JSON.stringify(object, getCircularReplacer(), " ".repeat(indent))])
  142. debug(`blob=<Blob size=${blob.size}>, filename=${filename}, indent=${indent}`);
  143. var a = window.document.createElement('a');
  144. a.href = window.URL.createObjectURL(blob, {type: 'text/json'});
  145. a.download = filename;
  146.  
  147. // Append anchor to body.
  148. document.body.appendChild(a);
  149. a.dispatchEvent(new MouseEvent('click'));
  150.  
  151. // Remove anchor from body
  152. document.body.removeChild(a);
  153. }
  154.  
  155. /* Export stuff */
  156.  
  157. unsafeWindow.mapToStyle = mapToStyle;
  158. unsafeWindow.Debugger = Debugger;
  159. unsafeWindow.getCircularReplacer = getCircularReplacer;
  160. unsafeWindow.downloadObjectJSON = downloadObjectJSON;
  161. unsafeWindow.debug = debug;
  162. unsafeWindow.info = info;
  163. unsafeWindow.warn = warn;
  164. unsafeWindow.error = error;