UNPKG

@whitesev/utils

Version:

一个常用的工具库

234 lines (229 loc) 7.7 kB
import type { UtilsLogOptions } from "./types/Log"; export class Log { /** 是否禁用输出的flag */ #disable: boolean = false; /** 前面的TAG标志 */ tag: string = "Utils.Log"; /* 使用的console函数 */ #console: Console = null as any; /* 当前输出的数量 */ #logCount = 0; /* 配置 */ #details: UtilsLogOptions = { tag: true, successColor: "background: #0eac0eff;", errorColor: "background: #FF0000;", infoColor: "background: #6495ed;", warnColor: "background: #ff8c00;", debug: false, autoClearConsole: false, logMaxCount: 999, }; /** * 通用样式配置 */ #commonStyleConfig = { commonStyle: "color: #ffffff; padding: 3px; border-radius: 3px;line-height: 1;margin-right: 6px;", tagStyle: "background: #6495ed;", callerNameStyle: "background: #78909C;", }; /** * @param __GM_info 油猴管理器的API GM_info,或者是一个对象,如{"script":{name:"Utils.Log"}},或者直接是一个字符串,用作tag名 * @param console 可指定console对象为unsafeWindow下的console或者是油猴window下的console */ constructor( __GM_info?: | { script: { name: string; }; } | string, console: Console = window.console ) { if (typeof __GM_info === "string") { this.tag = __GM_info; } else if (typeof __GM_info === "object" && typeof __GM_info?.script?.name === "string") { this.tag = __GM_info.script.name; } this.#console = console; } /** * 解析Error的堆栈获取实际调用者的函数名及函数所在的位置 * @param stack */ private parseErrorStack(stack: string[]) { const result = { name: "", position: "", }; for (let stackString of stack) { stackString = stackString.trim(); const stackFunctionNameMatch = stackString.match(/^at[\s]+(.+?)[\s]+/i); const stackFunctionNamePositionMatch = stackString.match(/^at[\s]+.+[\s]+\((.+?)\)/i); if (stackFunctionNameMatch == null) { continue; } if (stackFunctionNamePositionMatch == null) { continue; } /* 获取最后一个,因为第一个是包含了at */ const stackFunctionName = stackFunctionNameMatch[stackFunctionNameMatch.length - 1]; const stackFunctionNamePosition = stackFunctionNamePositionMatch[stackFunctionNamePositionMatch.length - 1]; if ( stackFunctionName === "" || stackFunctionName.match(/^(Utils\.|)Log(\.|)|.<anonymous>$|^Function.each|^NodeList.forEach|^k.fn.init.each/g) ) { continue; } else { result.name = stackFunctionName; result.position = stackFunctionNamePosition; break; } } if (result.position === "") { const lastStackString = stack[stack.length - 1].trim(); if (lastStackString.startsWith("at chrome-extension://")) { const lastStackMatch = lastStackString.match(/^at[\s]+(.+)/); if (lastStackMatch) { result.position = lastStackMatch[lastStackMatch.length - 1]; } } } if (result.position === "") { result.position = stack[stack.length - 1].trim().replace(/^at[\s]*/g, ""); } return result; } /** * 检测清理控制台 */ private checkClearConsole() { this.#logCount++; if (this.#details.autoClearConsole && this.#logCount > this.#details.logMaxCount) { this.#console.clear(); this.#logCount = 0; } } /** * 输出内容 * @param msg 需要输出的内容 * @param tagColor tag颜色 */ private printContent(msg: any[], tagColor?: string) { this.checkClearConsole(); const stackSplit = new Error()!.stack!.split("\n"); stackSplit.splice(0, 2); const { name: callerName, position: callerPosition } = this.parseErrorStack(stackSplit); const tagName = this.tag; const that = this; const msgColorDetails: string[] = []; // 控制台输出的tag的html格式 let consoleHTML = `%c${tagName}`; /** tag的html输出格式 */ if (typeof tagColor === "string" && tagColor.trim() !== "") { msgColorDetails.push(that.#commonStyleConfig.commonStyle + tagColor); } else { msgColorDetails.push(that.#commonStyleConfig.commonStyle + that.#commonStyleConfig.tagStyle); } // 调用的函数名的html输出格式 if (callerName.trim() == "") { // 无调用函数名 } else { consoleHTML = `${consoleHTML}%c${callerName}`; msgColorDetails.push(that.#commonStyleConfig.commonStyle + that.#commonStyleConfig.callerNameStyle); } if (Array.isArray(msg)) { that.#console.log(`${consoleHTML}`, ...msgColorDetails, ...msg); } else { that.#console.log(`${consoleHTML}`, ...msgColorDetails, msg); } if (this.#details.debug) { /* 如果开启调试模式,输出堆栈位置 */ this.#console.log(callerPosition); } } /** * 控制台-普通输出 * @param args 需要输出的内容 * @example * log.info("输出信息","输出信息2","输出信息3","输出") */ info(...args: any[]) { if (this.#disable) return; this.printContent(args, this.#details.infoColor); } /** * 控制台-警告输出 * @param args 需要输出的内容 * @example * log.warn("输出警告","输出警告2","输出警告3","输出警告4") */ warn(...args: any[]) { if (this.#disable) return; // , "background: #FEF6D5;padding: 4px 6px 4px 0px;" this.printContent(args, this.#details.warnColor); } /** * 控制台-错误输出 * @param args 需要输出的内容 * @example * log.error("输出错误","输出错误2","输出错误3","输出错误4") */ error(...args: any[]) { if (this.#disable) return; this.printContent(args, this.#details.errorColor); } /** * 控制台-成功输出 * @param args 需要输出的内容 * @example * log.success("输出成功") */ success(...args: any[]) { if (this.#disable) return; this.printContent(args, this.#details.successColor); } /** * 控制台-输出表格 * @param msg 需要输出的内容 * @example * log.table([{"名字":"example","值":"123"},{"名字":"example2","值":"345"}]) */ table(msg: any[]) { if (this.#disable) return; this.checkClearConsole(); const stack = new Error()!.stack!.split("\n"); stack.splice(0, 1); const errorStackParse = this.parseErrorStack(stack); /** 堆栈函数名 */ const stackFunctionName = errorStackParse.name; /** 堆栈位置 */ const stackFunctionNamePosition = errorStackParse.position; const callerName = stackFunctionName; const msgColorDetails: string[] = [ `${this.#commonStyleConfig.commonStyle + this.#details.infoColor}`, `${this.#commonStyleConfig.commonStyle + this.#commonStyleConfig.callerNameStyle}`, ]; this.#console.log(`%c${this.tag}%c${callerName}%c`, msgColorDetails); this.#console.table(msg); if (this.#details.debug) { this.#console.log(stackFunctionNamePosition); } } /** * 配置Log对象的颜色 * @param paramDetails 配置信息 */ config(paramDetails: Partial<UtilsLogOptions>) { this.#details = Object.assign(this.#details, paramDetails); } /** 禁用输出 */ disable() { this.#disable = true; } /** 恢复输出 */ recovery() { this.#disable = false; } }