UNPKG

@whitesev/utils

Version:

一个常用的工具库

278 lines (272 loc) 7.51 kB
import type { UtilsLogOptions } from "./types/Log"; class Log { /** 是否禁用输出的flag */ #disable: boolean = false; /** 前面的TAG标志 */ tag: string = "Utils.Log"; /* 使用的console函数 */ #console: Console = null as any; /* 当前输出的数量 */ #logCount = 0; /* 配置 */ #details: UtilsLogOptions = { tag: true, successColor: "#0000FF", errorColor: "#FF0000", infoColor: "0", warnColor: "0", debug: false, autoClearConsole: false, logMaxCount: 999, }; /** * 颜色配置 */ #msgColorDetails = [ "font-weight: bold; color: cornflowerblue", "font-weight: bold; color: cornflowerblue", "font-weight: bold; color: darkorange", "font-weight: bold; color: cornflowerblue", ]; /** * @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[]) { let result = { name: "", position: "", }; for (let stackString of stack) { stackString = stackString.trim(); let stackFunctionNameMatch = stackString.match(/^at[\s]+(.+?)[\s]+/i); let stackFunctionNamePositionMatch = stackString.match( /^at[\s]+.+[\s]+\((.+?)\)/i ); if (stackFunctionNameMatch == null) { continue; } if (stackFunctionNamePositionMatch == null) { continue; } /* 获取最后一个,因为第一个是包含了at */ let stackFunctionName = stackFunctionNameMatch[stackFunctionNameMatch.length - 1]; let 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 === "") { let lastStackString = stack[stack.length - 1].trim(); if (lastStackString.startsWith("at chrome-extension://")) { let 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 color 颜色 * @param otherStyle 其它CSS */ private printContent(msg: any[], color: string, otherStyle?: string) { this.checkClearConsole(); otherStyle = otherStyle || ""; let stackSplit = new Error()!.stack!.split("\n"); stackSplit.splice(0, 2); let { name: callerName, position: callerPosition } = this.parseErrorStack(stackSplit); let tagName = this.tag; let that = this; /** tag的html输出格式 */ let tagNameHTML = `%c[${tagName}%c`; /** 调用的函数名的html输出格式 */ let callerNameHTML = `%c${callerName}%c]%c`; callerName.trim() !== "" && (callerNameHTML = "-" + callerNameHTML); /** * 输出消息到控制台 * @param message */ function consoleMsg(message: any) { if (typeof message === "string") { that.#console.log( `${tagNameHTML}${callerNameHTML} %s`, ...that.#msgColorDetails, `color: ${color};${otherStyle}`, message ); } else if (typeof message === "number") { that.#console.log( `${tagNameHTML}${callerNameHTML} %d`, ...that.#msgColorDetails, `color: ${color};${otherStyle}`, message ); } else if (typeof message === "object") { that.#console.log( `${tagNameHTML}${callerNameHTML} %o`, ...that.#msgColorDetails, `color: ${color};${otherStyle}`, message ); } else { that.#console.log(message); } } if (Array.isArray(msg)) { for (let index = 0; index < msg.length; index++) { consoleMsg(msg[index]); } } else { consoleMsg(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; this.printContent( args, this.#details.warnColor, "background: #FEF6D5;padding: 4px 6px 4px 0px;" ); } /** * 控制台-错误输出 * @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(); let stack = new Error()!.stack!.split("\n"); stack.splice(0, 1); let errorStackParse = this.parseErrorStack(stack); /** 堆栈函数名 */ let stackFunctionName = errorStackParse.name; /** 堆栈位置 */ let stackFunctionNamePosition = errorStackParse.position; let callerName = stackFunctionName; this.#console.log( `%c[${this.tag}%c-%c${callerName}%c]%c`, ...this.#msgColorDetails, `color: ${this.#details.infoColor};` ); 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; } } export { Log };