您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
主要用于日志检测脚本的调用
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/440535/1021754/debugout.js
- /*
- debugout.js
- by @inorganik
- */
- // save all the console.logs
- function debugout() {
- var self = this;
- // OPTIONS
- self.realTimeLoggingOn = true; // log in real time (forwards to console.log)
- self.useTimestamps = false; // insert a timestamp in front of each log
- self.useLocalStorage = false; // store the output using window.localStorage() and continuously add to the same log each session
- self.recordLogs = true; // set to false after you're done debugging to avoid the log eating up memory
- self.autoTrim = true; // to avoid the log eating up potentially endless memory
- self.maxLines = 2500; // if autoTrim is true, this many most recent lines are saved
- self.tailNumLines = 100; // how many lines tail() will retrieve
- self.logFilename = 'debugout.txt'; // filename of log downloaded with downloadLog()
- // vars
- self.depth = 0;
- self.parentSizes = [0];
- self.currentResult = '';
- self.startTime = new Date();
- self.output = '';
- this.version = function() { return '0.5.0' }
- /*
- USER METHODS
- */
- this.getLog = function() {
- var retrievalTime = new Date();
- // if recording is off, so dev knows why they don't have any logs
- if (!self.recordLogs) {
- self.log('[debugout.js] log recording is off.');
- }
- // if using local storage, get values
- if (self.useLocalStorage) {
- var saved = window.localStorage.getItem('debugout.js');
- if (saved) {
- saved = JSON.parse(saved);
- self.startTime = new Date(saved.startTime);
- self.output = saved.log;
- retrievalTime = new Date(saved.lastLog);
- }
- }
- return self.output
- + '\n---- Log retrieved: '+retrievalTime+' ----\n'
- + self.formatSessionDuration(self.startTime, retrievalTime);
- }
- // accepts optional number or uses the default for number of lines
- this.tail = function(numLines) {
- var numLines = numLines || self.tailLines;
- return self.trimLog(self.getLog(), numLines);
- }
- // accepts a string to search for
- this.search = function(string) {
- var lines = self.output.split('\n');
- var rgx = new RegExp(string);
- var matched = [];
- // can't use a simple Array.prototype.filter() here
- // because we need to add the line number
- for (var i = 0; i < lines.length; i++) {
- var addr = '['+i+'] ';
- if (lines[i].match(rgx)) {
- matched.push(addr + lines[i]);
- }
- }
- var result = matched.join('\n');
- if (result.length == 0) result = 'Nothing found for "'+string+'".';
- return result
- }
- // accepts the starting line and how many lines after the starting line you want
- this.getSlice = function(lineNumber, numLines) {
- var lines = self.output.split('\n');
- var segment = lines.slice(lineNumber, lineNumber + numLines);
- return segment.join('\n');
- }
- // immediately downloads the log - for desktop browser use
- this.downloadLog = function() {
- var file = "data:text/plain;charset=utf-8,";
- var logFile = self.getLog();
- var encoded = encodeURIComponent(logFile);
- file += encoded;
- var a = document.createElement('a');
- a.href = file;
- a.target = '_blank';
- a.download = self.logFilename;
- document.body.appendChild(a);
- a.click();
- a.remove();
- }
- // clears the log
- this.clear = function() {
- var clearTime = new Date();
- self.output = '---- Log cleared: '+clearTime+' ----\n';
- if (self.useLocalStorage) {
- // local storage
- var saveObject = {
- startTime: self.startTime,
- log: self.output,
- lastLog: clearTime
- }
- saveObject = JSON.stringify(saveObject);
- window.localStorage.setItem('debugout.js', saveObject);
- }
- if (self.realTimeLoggingOn) console.log('[debugout.js] clear()');
- }
- // records a log
- this.log = function(obj) {
- // log in real time
- if (self.realTimeLoggingOn) console.log(obj);
- // record log
- var type = self.determineType(obj);
- if (type != null && self.recordLogs) {
- var addition = self.formatType(type, obj);
- // timestamp, formatted for brevity
- if (self.useTimestamps) {
- var logTime = new Date();
- self.output += self.formatTimestamp(logTime);
- }
- self.output += addition+'\n';
- if (self.autoTrim) self.output = self.trimLog(self.output, self.maxLines);
- // local storage
- if (self.useLocalStorage) {
- var last = new Date();
- var saveObject = {
- startTime: self.startTime,
- log: self.output,
- lastLog: last
- }
- saveObject = JSON.stringify(saveObject);
- window.localStorage.setItem('debugout.js', saveObject);
- }
- }
- self.depth = 0;
- self.parentSizes = [0];
- self.currentResult = '';
- }
- /*
- METHODS FOR CONSTRUCTING THE LOG
- */
- // like typeof but classifies objects of type 'object'
- // kept separate from formatType() so you can use at your convenience!
- this.determineType = function(object) {
- if (object != null) {
- var typeResult;
- var type = typeof object;
- if (type == 'object') {
- var len = object.length;
- if (len == null) {
- if (typeof object.getTime == 'function') {
- typeResult = 'Date';
- }
- else if (typeof object.test == 'function') {
- typeResult = 'RegExp';
- }
- else {
- typeResult = 'Object';
- }
- } else {
- typeResult = 'Array';
- }
- } else {
- typeResult = type;
- }
- return typeResult;
- } else {
- return null;
- }
- }
- // format type accordingly, recursively if necessary
- this.formatType = function(type, obj) {
- switch(type) {
- case 'Object' :
- self.currentResult += '{\n';
- self.depth++;
- self.parentSizes.push(self.objectSize(obj));
- var i = 0;
- for (var prop in obj) {
- self.currentResult += self.indentsForDepth(self.depth);
- self.currentResult += prop + ': ';
- var subtype = self.determineType(obj[prop]);
- var subresult = self.formatType(subtype, obj[prop]);
- if (subresult) {
- self.currentResult += subresult;
- if (i != self.parentSizes[self.depth]-1) self.currentResult += ',';
- self.currentResult += '\n';
- } else {
- if (i != self.parentSizes[self.depth]-1) self.currentResult += ',';
- self.currentResult += '\n';
- }
- i++;
- }
- self.depth--;
- self.parentSizes.pop();
- self.currentResult += self.indentsForDepth(self.depth);
- self.currentResult += '}';
- if (self.depth == 0) return self.currentResult;
- break;
- case 'Array' :
- self.currentResult += '[';
- self.depth++;
- self.parentSizes.push(obj.length);
- for (var i = 0; i < obj.length; i++) {
- var subtype = self.determineType(obj[i]);
- if (subtype == 'Object' || subtype == 'Array') self.currentResult += '\n' + self.indentsForDepth(self.depth);
- var subresult = self.formatType(subtype, obj[i]);
- if (subresult) {
- self.currentResult += subresult;
- if (i != self.parentSizes[self.depth]-1) self.currentResult += ', ';
- if (subtype == 'Array') self.currentResult += '\n';
- } else {
- if (i != self.parentSizes[self.depth]-1) self.currentResult += ', ';
- if (subtype != 'Object') self.currentResult += '\n';
- else if (i == self.parentSizes[self.depth]-1) self.currentResult += '\n';
- }
- }
- self.depth--;
- self.parentSizes.pop();
- self.currentResult += ']';
- if (self.depth == 0) return self.currentResult;
- break;
- case 'function' :
- obj += '';
- var lines = obj.split('\n');
- for (var i = 0; i < lines.length; i++) {
- if (lines[i].match(/\}/)) self.depth--;
- self.currentResult += self.indentsForDepth(self.depth);
- if (lines[i].match(/\{/)) self.depth++;
- self.currentResult += lines[i] + '\n';
- }
- return self.currentResult;
- break;
- case 'RegExp' :
- return '/'+obj.source+'/';
- break;
- case 'Date' :
- case 'string' :
- if (self.depth > 0 || obj.length == 0) {
- return '"'+obj+'"';
- } else {
- return obj;
- }
- case 'boolean' :
- if (obj) return 'true';
- else return 'false';
- case 'number' :
- return obj+'';
- break;
- }
- }
- this.indentsForDepth = function(depth) {
- var str = '';
- for (var i = 0; i < depth; i++) {
- str += '\t';
- }
- return str;
- }
- this.trimLog = function(log, maxLines) {
- var lines = log.split('\n');
- if (lines.length > maxLines) {
- lines = lines.slice(lines.length - maxLines);
- }
- return lines.join('\n');
- }
- this.lines = function() {
- return self.output.split('\n').length;
- }
- // calculate testing time
- this.formatSessionDuration = function(startTime, endTime) {
- var msec = endTime - startTime;
- var hh = Math.floor(msec / 1000 / 60 / 60);
- var hrs = ('0' + hh).slice(-2);
- msec -= hh * 1000 * 60 * 60;
- var mm = Math.floor(msec / 1000 / 60);
- var mins = ('0' + mm).slice(-2);
- msec -= mm * 1000 * 60;
- var ss = Math.floor(msec / 1000);
- var secs = ('0' + ss).slice(-2);
- msec -= ss * 1000;
- return '---- Session duration: '+hrs+':'+mins+':'+secs+' ----'
- }
- this.formatTimestamp = function(timestamp) {
- var year = timestamp.getFullYear();
- var date = timestamp.getDate();
- var month = ('0' + (timestamp.getMonth() +1)).slice(-2);
- var hrs = Number(timestamp.getHours());
- var mins = ('0' + timestamp.getMinutes()).slice(-2);
- var secs = ('0' + timestamp.getSeconds()).slice(-2);
- return '['+ year + '-' + month + '-' + date + ' ' + hrs + ':' + mins + ':'+secs + ']: ';
- }
- this.objectSize = function(obj) {
- var size = 0, key;
- for (key in obj) {
- if (obj.hasOwnProperty(key)) size++;
- }
- return size;
- }
- /*
- START/RESUME LOG
- */
- if (self.useLocalStorage) {
- var saved = window.localStorage.getItem('debugout.js');
- if (saved) {
- saved = JSON.parse(saved);
- self.output = saved.log;
- var start = new Date(saved.startTime);
- var end = new Date(saved.lastLog);
- self.output += '\n---- Session end: '+saved.lastLog+' ----\n';
- self.output += self.formatSessionDuration(start, end);
- self.output += '\n\n';
- }
- }
- self.output += '---- Session started: '+self.startTime+' ----\n\n';
- }