Dev stuff

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

当前为 2024-08-02 提交的版本,查看 最新版本

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

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

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址