UNPKG

chocolog

Version:

A highlighted android-style logger

980 lines 35 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const ansi_parser_1 = __importDefault(require("ansi-parser")); const chalk_1 = __importDefault(require("chalk")); const color_1 = __importDefault(require("color")); const color_blend_1 = require("color-blend"); const emphasize_1 = __importDefault(require("emphasize")); const fs_extra_1 = __importDefault(require("fs-extra")); const node_fetch_1 = __importDefault(require("node-fetch")); const path_1 = __importDefault(require("path")); const stack_trace_1 = __importDefault(require("stack-trace")); const stringify_object_1 = __importDefault(require("stringify-object")); const deepreadonly_1 = require("../types/deepreadonly"); const colordefine_1 = require("./colordefine"); const loglv_1 = require("./loglv"); const monoutil_1 = require("./monoutil"); const tostr_1 = require("./tostr"); const tsmap_1 = __importDefault(require("./tsmap")); const vs2015css_1 = require("./vs2015css"); if (useOrigin()) { // module to extends stacktrace // this is MUST require for duplicate stacktrace tracking require("trace"); require("clarify"); } const jsPath = __filename; class ChocoLog { // protected headerChalk = chalk. constructor(name) { /** * Use AM/PM instead of 24-hours? */ this.use12Hour = false; /** * Min header size */ this.minHeaderSize = 24; // ======================================================== /** * Log Levels defines */ this.levels = deepreadonly_1.asReadonly(Object.assign({}, loglv_1.LogLvStatic)); /** * General colors (all used to type) */ this.generalColors = { back: "#222222", backSub: "#333333", backInfo: "#444444", text: "#eeeeee", }; this.middleSize = 3; this.subpadSize = 1; this.cwd = process.cwd(); this.sourceMap = new Map(); this.name = name; this.logLevel = ChocoLog.defaultLevel; this.setCssTheme(vs2015css_1.vs2015CSS); } /** * Default theme * * Used in text content */ get defaultTheme() { return chalk_1.default.bgHex(this.generalColors.back).hex(this.generalColors.text); } get width() { return process.stdout.columns; } get headerSize() { return Math.min(this.minHeaderSize, Math.floor(this.width / 4)); } get timestamp() { const time = new Date(Date.now()); let h = time.getHours(); const isPM = h >= 12; if (this.use12Hour) { if (isPM) { h -= 12; } if (h === 0) { h = 12; } } const pad = (n) => n.toString(10).padStart(2, "0"); const month = pad(time.getMonth() + 1); const day = pad(time.getDate()); const m = pad(time.getMinutes()); const s = pad(time.getSeconds()); const ms = time.getMilliseconds().toString(10).padStart(3, "0"); return `${this.use12Hour ? (isPM ? "P" : "A") : ""}${pad(h)}:${m}:${s}.${ms}`; } /* ===================================================== = Define default methods = Due to callback detector, we should copy-paste code. ===================================================== */ /** * Prints *debug* log. (Loglevel 2) * @param title Title of logger. If none, this is used to content * @param desc Contents to print */ d(title, ...desc) { const [strTitle, strDesc] = this.fallbackParam(title, desc); return this.printSimple(strTitle, strDesc, { tagName: "D", colorTheme: this.typedColors.debug, fontColor: this.generalColors.text, level: this.levels.DEBUG, }); } /** * Prints *verbose* log. (Loglevel 1) * @param title Title of logger. If none, this is used to content * @param desc Contents to print */ v(title, ...desc) { const [strTitle, strDesc] = this.fallbackParam(title, desc); return this.printSimple(strTitle, strDesc, { tagName: "V", colorTheme: this.generalColors.text, fontColor: this.generalColors.text, level: this.levels.VERBOSE, }); } /** * Prints *info* log. (Loglevel 3) * @param title Title of logger. If none, this is used to content * @param desc Contents to print */ i(title, ...desc) { const [strTitle, strDesc] = this.fallbackParam(title, desc); return this.printSimple(strTitle, strDesc, { tagName: "I", colorTheme: this.typedColors.info, fontColor: this.generalColors.text, level: this.levels.INFO, }); } /** * Prints *warn* log. (Loglevel 4) * @param title Title of logger. If none, this is used to content * @param desc Contents to print */ w(title, ...desc) { const [strTitle, strDesc] = this.fallbackParam(title, desc); return this.printSimple(strTitle, strDesc, { tagName: "W", colorTheme: this.typedColors.warn, fontColor: this.generalColors.text, level: this.levels.WARN, }); } /** * Prints *error* log. (Loglevel 5) * @param title Title of logger. If none, this is used to content * @param desc Contents to print */ e(title, ...desc) { const [strTitle, strDesc] = this.fallbackParam(title, desc); this.printSimple(strTitle, strDesc, { tagName: "E", colorTheme: this.typedColors.error, fontColor: this.typedColors.error, level: this.levels.ERROR, }); return null; } /** * ☠ (Loglevel **6**) * @param title Title of logger. If none, this is used to content * @param desc Contents to print */ wtf(title, ...desc) { const params = this.fallbackParam(title, desc); return this.printSimple(params[0], params[1], { tagName: "F", colorTheme: this.typedColors.assert, fontColor: this.typedColors.assert, level: this.levels.ASSERT, }); } /** * Log programming code with formatter * * used `highlight.js` wrapper `emphasize` * @param codeContent Code string to print (css, js, etc...) * @param title Title of log, not need at normal. * @param lang The language of the code. If non-specic, Library will auto detect */ code(codeContent, title, lang) { let _title; if (title == null) { _title = "Code"; } else { _title = this.toStr(title); } const desc = this.beautyCode(codeContent, lang); return this.printSimple(_title, desc, { tagName: "C", colorTheme: this.generalColors.text, fontColor: this.generalColors.text, level: this.levels.VERBOSE, }); } /** * Set `highlight.js` theme to console * * Almost check [highlight.js github](https://github.com/highlightjs/highlight.js/tree/master/src/styles) * * Scss not supported. * @param css css text */ setCssTheme(css) { // get hljs global css const queryHljs = getFirst(css.match(/\.hljs\s*{[\S\s]+?}/)); if (queryHljs == null) { // wtf this.wtf("setCssTheme", "QueryHljs being null!"); this.code(css, "CSSInfo", "css"); return this.codeStyle; } // background color search const queryBack = getFirst(queryHljs.match(/^\s*background:.+?;/im)); let codeBackground; let codeTextColor; if (queryBack != null) { try { codeBackground = cssToColor(queryBack.trim()); } catch (err) { this.w("setCodeTheme", "Color_bg parse Failed\n", err); } } // foreground color search const queryFore = getFirst(queryHljs.match(/^\s*color:.+?;/im)); if (queryFore != null) { try { codeTextColor = cssToColor(queryFore.trim()); } catch (err) { this.w("setCodeTheme", "Color_text parse Failed.\n", err); } } this.setBgTheme(codeBackground == null ? this.generalColors.back : codeBackground, codeTextColor); // child style search const queries = css.match(/\.hljs-[a-zA-Z\-_,.\s]+?{[\S\s]+?}/g); const styles = {}; for (const query of queries) { // 1. color let color = null; try { color = cssToColor(getFirst(query.match(/color:.+;/))); } catch (err) { this.w("setCodeTheme", "ColorText parse failed.\n", err); } let colorBack; try { colorBack = cssToColor(getFirst(query.match(/background-color:.+;/))); } catch (err) { this.w("setCodeTheme", "ColorBack parse failed.\n", err); } const bold = query.match(/font-weight:\s*bold;/) != null; const italic = query.match(/font-style:\s*italic;/) != null; const underline = query.match(/text-decoration:\s*underline;/) != null; const headers = query.match(/.hljs-.+/ig); if (headers == null) { continue; } for (const header of headers) { let head = header.replace(/^\.hljs-/i, "").replace(/,\s*/i, "").replace("{", "").trim(); if (head === "constructor") { head = "_" + head; } let style = styles[head]; if (style === undefined) { style = chalk_1.default; } if (color != null) { style = style.hex(color); } if (colorBack != null) { style = style.bgHex(colorBack); } if (bold) { style = style.bold; } if (italic) { style = style.italic; } if (underline) { style = style.underline; } styles[head] = style; } } if (styles["_constructor"] != null) { styles["constructor"] = styles["_constructor"]; } this.codeStyle = styles; return styles; } /** * Set background & text color * * Auto modify type colors. * @param background Background of terminal * @param textColor The default text color of terminal */ setBgTheme(background, textColor) { const bgColor = color_1.default(background).hsv(); if (textColor === undefined) { if (bgColor.isDark()) { textColor = "#dddddd"; } else { textColor = "#111111"; } } const bgValue = bgColor.value(); const toHex = (cl) => { return cl.hex().replace("0x", "#"); }; const genColor = (hue) => { const sat = Math.round(25 + (bgValue) * 0.55); const val = Math.round(55 + (100 - bgValue) * 0.45); return toHex(color_1.default({ h: hue, s: sat, v: val })); }; const obj = {}; for (const [k, v] of Object.entries(colordefine_1.hueColors)) { obj[k] = genColor(v); } this.typedColors = obj; this.generalColors.back = background; this.generalColors.text = textColor; if (bgColor.isDark()) { const fn = (n) => { if (bgColor.value() <= 0.05) { const hex = (Math.floor(n * 80)).toString(16).toUpperCase(); return color_1.default(`#${hex}${hex}${hex}`); } return bgColor.lighten(n); }; this.generalColors.backSub = toHex(fn(0.2)); this.generalColors.backInfo = toHex(fn(0.3)); } else { const fn = (n) => { return bgColor.darken(n); }; this.generalColors.backSub = toHex(fn(0.1)); this.generalColors.backInfo = toHex(fn(0.3)); } } /** * Apply Highlight.js style from github * * https://github.com/highlightjs/highlight.js * @param type Highlight.js style */ async setStyleGithub(type) { const url = `https://raw.githubusercontent.com/highlightjs/highlight.js/master/src/styles/${type}.css`; const css = await node_fetch_1.default(url).then((v) => v.text()); this.setCssTheme(css); } /* ===================================================== = Utility part ===================================================== */ // Level part /** * Get current loglevel * * Let's see [loglevel doc](https://www.npmjs.com/package/loglevel) */ getLevel() { return this.logLevel; } /** * Set loglevel to `level` * * Let's see [loglevel doc](https://www.npmjs.com/package/loglevel) * @param level The minimum level to want logging */ setLevel(level) { const setLog = this.decodeLogLevel(level); if (setLog === -1) { return; } this.logLevel = setLog; } /** * Set default loglevel to `level` * * This doesn't applies copied object but will be copyed object * @param level The minimum level to want logging */ setDefaultLevel(level) { const setLog = this.decodeLogLevel(level); if (setLog === -1) { return; } ChocoLog.defaultLevel = setLog; } /** * Enable all log messages * * Same as `setLevel(cLog.levels.ALL)` * * See [loglevel doc](https://www.npmjs.com/package/loglevel) */ enableAll() { this.logLevel = loglv_1.LogLv.ALL; } /** * Disable all log messages * * Same as `setLevel(cLog.levels.SLIENT)` * * See [loglevel doc](https://www.npmjs.com/package/loglevel) */ disableAll() { this.logLevel = loglv_1.LogLv.SILENT; } /* ==== Clone Part */ /** * Clones this Log class and returns it * @param name New logger's name */ getLogger(name) { const cloned = new ChocoLog(name); // level cloned.setLevel(ChocoLog.defaultLevel); // code style cloned.codeStyle = this.codeStyle; // color theme cloned.generalColors = Object.assign({}, this.generalColors); cloned.typedColors = Object.assign({}, this.typedColors); // etc conf cloned.use12Hour = this.use12Hour; cloned.minHeaderSize = this.minHeaderSize; return cloned; } /** * Let's trace error beauty * @param err Error */ errorToString(err) { const rawStacks = this.filterStack(stack_trace_1.default.parse(err)); const stackes = []; for (const stack of rawStacks) { stackes.push(this.encodeCaller(this.decodeStack(stack))); } return `[${err.name}] ${err.message}\n${stackes.map((v) => ` at ${v}`).join("\n")}`; } /** * Decode LogLv to number * @param level LogLv */ decodeLogLevel(level) { if (typeof level === "string") { for (const [key, value] of Object.entries(this.levels)) { if (key.toUpperCase() === level.toUpperCase()) { return value; } } } return -1; } /** * Something type to string (Maybe recursive) * @param obj any object or number or etc.. */ toStr(obj, beauty = true) { const cubeCache = []; const toJSONOpt = { indent: tostr_1.indenter, singleQuotes: false, inlineCharacterLimit: 30, transform: (o, prop, value) => { if (o[prop] instanceof Date) { return o[prop].toString(); } else if (o[prop] instanceof Error) { const str = `\u{1F4A5} ${this.errorToString(o[prop])}`; value = tostr_1.forceIndent(str); value = chalk_1.default.hex(this.typedColors.error)(value); } else if (o[prop] instanceof Map) { const toObj = this.mapToObject(o[prop]); value = tostr_1.forceIndent(stringify_object_1.default(toObj, toJSONOpt)); } else if (typeof o[prop] === "function") { // return value value = this.beautyCode(value); } else { // return value } const ansies = value.match(monoutil_1.ansiExp); if (ansies != null) { cubeCache.push(value); value = `\u{FFF5}_A${tostr_1.encodeNo(cubeCache.length - 1)}_`; } return value; // .replace(new RegExp("\x1B\\[", "ig"), "\u{FFF5}_C>") }, }; if (obj === null) { if (beauty) { // return chalk.italic("null") return "null"; } else { return "null"; } } if (obj === undefined) { if (beauty) { // return chalk.italic("undefined") return "undefined"; } else { return "undefined"; } } switch (typeof obj) { case "string": return obj; case "boolean": case "number": case "symbol": case "bigint": return obj.toString(); } if (obj instanceof Buffer) { return obj.toString(); } if (obj instanceof Error) { return this.errorToString(obj); } if (obj instanceof Date) { return obj.toString(); } if (obj instanceof Map || typeof obj === "object" || typeof obj === "function") { if (obj instanceof Map) { obj = this.mapToObject(obj); } let json = stringify_object_1.default(obj, toJSONOpt); let lastIntentNum = 0; let lastValNameNum = 0; // 1. beauty if (beauty) { json = this.beautyJSON(json); } // 2. decode const ansiRep = json.match(new RegExp(`\u{FFF5}_A.+?_`, "g")); if (ansiRep != null) { for (const ansiR of ansiRep) { const str = ansiR.match(/_A.+?_/i)[0]; const index = tostr_1.decodeNo(str.substring(2, str.length - 1)); json = json.replace(ansiR, cubeCache[index]); } } // 3. tab if (json.indexOf(tostr_1.forceIndenter) >= 0) { const lines = json.split("\n"); for (let i = 0; i < lines.length; i += 1) { let line = lines[i]; const nonStyleLine = monoutil_1.stripAnsi(line); let intentNum = 0; if (!nonStyleLine.startsWith(tostr_1.indenter) && !nonStyleLine.startsWith(tostr_1.forceIndenter)) { continue; } while (line.startsWith(tostr_1.indenter)) { line = line.replace(tostr_1.indenter, ""); intentNum += 1; } const valName = line.match(/^.*?:\s*/i); let valNameLn = -1; if (valName != null) { valNameLn = monoutil_1.consoleLn(valName[0]); } const isForcedIntenter = nonStyleLine.startsWith(tostr_1.forceIndenter); if (isForcedIntenter) { let madeIntent = ""; for (let k = 0; k < lastIntentNum; k += 1) { madeIntent += tostr_1.indenter; } lines[i] = line .replace(tostr_1.forceIndenter, madeIntent) .replace(tostr_1.valNameIndenter, monoutil_1.makeBlank(lastValNameNum)); } if (valNameLn >= 0 && !isForcedIntenter) { lastValNameNum = valNameLn; } if (intentNum > 0 && !isForcedIntenter) { lastIntentNum = intentNum; } } json = lines.join("\n"); } return json; } return ""; } fallbackParam(title, desc) { // tslint:disable-next-line let descStr = ""; if (desc == null || desc.length <= 0) { descStr = this.toStr(title); title = this.name.length < 1 ? ` ` : this.name; } else { title = this.toStr(title); for (const str of desc) { const _str = this.toStr(str); /* if (_str.indexOf("\n") >= 0 && !_str.startsWith("\n")) { _str = "\n" + _str } */ descStr += _str; } } if (!monoutil_1.ansiExp.test(descStr)) { descStr = this.beautyJSON(descStr); } let _title = title; if (_title.indexOf("\n") >= 0) { _title = _title.replace(/\s*\n\s*/ig, ""); } return [_title, descStr]; } mapToObject(map) { const KV = map.entries(); const obj = {}; for (const [key, value] of KV) { obj[this.toStr(key, false)] = value; } return obj; } encodeCaller(called) { return `${called.funcName} (${called.fileName}:${called.line}:${called.column})`; } caller() { const stackes = this.filterStack(stack_trace_1.default.get()); for (const stack of stackes) { const fname = stack.getFileName(); if (fname !== jsPath) { return this.decodeStack(stack); } } return this.decodeStack(stackes[stackes.length - 1]); } filterStack(stacktrace) { return stacktrace.filter((v, pos) => { return stacktrace.findIndex((_v) => _v.getFunctionName() === v.getFunctionName() && _v.getFileName() === v.getFileName()) === pos; }); } decodeStack(query) { // const lastEl = <T>(arr:T[]) => arr[arr.length - 1] let sourcepath = query.getFileName(); // const lastInfo = lastEl(sourcepath.split(/[\/\\]/ig)) let sourceLine = query.getLineNumber(); let sourceColumn = query.getColumnNumber(); const functionName = query.getFunctionName(); // functionName = functionName.substring(0, functionName.length - 1).trim() // functionName = functionName.substring(3, functionName.length) // sourcepath = sourcepath.substring(0, sourcepath.indexOf(":")) if (!this.sourceMap.has(sourcepath)) { const mapPath = `${sourcepath}.map`; if (fs_extra_1.default.pathExistsSync(mapPath)) { this.sourceMap.set(sourcepath, tsmap_1.default.from(mapPath)); } else { this.sourceMap.set(sourcepath, null); } } if (this.sourceMap.get(sourcepath) != null) { const sourceMap = this.sourceMap.get(sourcepath); const info = sourceMap.decodePoint(sourceLine, sourceColumn); if (info != null) { sourcepath = path_1.default.relative(this.cwd, sourceMap.getFilePath()); sourceLine = info.tsRow; sourceColumn = info.tsColumn; } else { sourcepath = path_1.default.relative(this.cwd, sourcepath); } } else { sourcepath = path_1.default.relative(this.cwd, sourcepath); } if (!sourcepath.startsWith(".")) { sourcepath = `.${path_1.default.sep}${sourcepath}`; } return { fileName: sourcepath, funcName: functionName, line: sourceLine, column: sourceColumn, }; } beautyCode(code, type) { let val; if (type !== undefined) { val = emphasize_1.default.highlight(type, code, this.codeStyle).value; } else { val = emphasize_1.default.highlightAuto(code, this.codeStyle).value; } return val; } beautyJSON(json) { return emphasize_1.default.highlight("json", json, this.codeStyle).value; } /** * Mix A and B, P P A P * @param color1 C2lor 1 * @param color2 Color 2 */ mixColor(color1, color2) { const decodeColor = (str, start, ln) => { return Number.parseInt(str.substr(start, ln), 16); }; const decodeColors = (str, alpha = 1) => { return { r: decodeColor(str, 1, 2), g: decodeColor(str, 3, 2), b: decodeColor(str, 5, 2), a: alpha, }; }; const encodeColors = (rgba) => { const encodeC = (n) => n.toString(16).padStart(2, "0"); const encodeCs = (...n) => n.map((v) => encodeC(v)).join(""); return `#${encodeCs(rgba.r, rgba.g, rgba.b)}`; }; if (color1.length < 2) { color1[1] = 1; } if (color2.length < 2) { color2[1] = 1; } return encodeColors(color_blend_1.normal(decodeColors(color1[0], color1[1]), decodeColors(color2[0], color2[1]))); } /** * Print Content with split & color & beauty * * This can't be optimized. * @param header * @param content * @param options */ printSimple(header, content, options) { // check log level if (this.logLevel > options.level) { return ""; } // define external properties const theme1 = this.defaultTheme.hex(options.fontColor); const theme2 = chalk_1.default.bgHex(this.generalColors.backSub).hex(options.fontColor); const theme = theme1.hex(options.colorTheme); /*.hex(options.fontColor) */ const callerFrom = this.caller(); let caller = ""; let encBottom = ""; if (callerFrom != null && useOrigin()) { caller = this.encodeCaller(callerFrom); encBottom = chalk_1.default.bgHex(this.generalColors.backInfo) .hex(options.colorTheme).italic(this.getFooter(caller)); } const encHeader = theme(`${this.getHeader(header, theme.inverse)} `) + theme.inverse(` ${options.tagName.substr(0, 1)} `) + theme1(" "); const middleStyle = theme.inverse; const encMiddle = `${this.getMiddle(middleStyle, options.tagName)}${theme(" ")}`; // split to fit const splitted = content.split("\n"); let largeDesign = false; if (splitted.length >= 3) { const lengthes = splitted.map((v) => v.length); let i = 0; for (const ln of lengthes) { i += ln; } splitted.splice(0, 0, chalk_1.default.italic(`${splitted.length}L, ${i}C${(caller.length >= 1) ? (", " + this.getFooter(caller).trimRight()) : ""}`)); largeDesign = true; } for (let i = 0; i < splitted.length; i += 1) { if (splitted[i] === "") { splitted[i] = " "; } } const lines = []; let maxLn0 = this.width - monoutil_1.consoleLn(encHeader) - 1; let maxLnA = this.width - monoutil_1.consoleLn(encMiddle) - 1; let lastStyle = null; for (let i = 0; i < splitted.length; i += 1) { const line = splitted[i]; const pureLineLn = monoutil_1.stripAnsi(line).length; let maxLn = i === 0 ? maxLn0 : maxLnA; let k = 0; while (k < pureLineLn) { const textInfo = monoutil_1.substrMono(line, k, maxLn); let text = textInfo.content; if (lastStyle != null && lastStyle.length > 0) { text = lastStyle + text; textInfo.lastStyle = ansi_parser_1.default.getAtIndex(text, monoutil_1.stripAnsi(text), monoutil_1.stripAnsi(text).length - 1).style; } lastStyle = textInfo.lastStyle; lines.push({ content: text, lineNo: i + 1, }); k += textInfo.original.length; maxLn = maxLnA; } if (lines.length >= 1) { lastStyle = null; lines[lines.length - 1] = { content: lines[lines.length - 1].content + `\x1B[0m`, lineNo: i + 1, }; } } // print // padding to end. (add 1 length to pad End.) maxLn0 += 1; maxLnA += 1; // tslint:disable-next-line let out = new String(); let lastLine = -1; const calcLnWithTab = (str, prefix) => { return monoutil_1.consoleLn(prefix + str) - monoutil_1.consoleLn(prefix); }; for (let i = 0; i < lines.length; i += 1) { const line = lines[i].content; const lineNo = lines[i].lineNo + (largeDesign ? -1 : 0); const lineTheme = lines[i].lineNo % 2 === 1 ? theme1 : theme2; let thisLine = ""; if (i === 0) { thisLine += encHeader; thisLine += lineTheme(line); if (i < lines.length - 1) { thisLine += lineTheme(monoutil_1.makeBlank(maxLn0 - calcLnWithTab(line, encHeader))); } } else { let indexVo = ""; if (lastLine !== lineNo) { indexVo = lineNo.toString(); } thisLine += `${this.getMiddle(middleStyle, monoutil_1.makeBlank(this.middleSize - monoutil_1.consoleLn(indexVo)) + indexVo)}${lineTheme(" ")}`; if (i < lines.length - 1) { thisLine += lineTheme(line) + lineTheme(monoutil_1.makeBlank(maxLnA - calcLnWithTab(line, thisLine))); } else { thisLine += lineTheme(line); } } if (i === lines.length - 1) { const left = this.width - monoutil_1.consoleLn(monoutil_1.stripAnsi(thisLine)); if (largeDesign) { thisLine += lineTheme(monoutil_1.makeBlank(this.width - monoutil_1.consoleLn(thisLine))); } else if (left >= monoutil_1.consoleLn(encBottom)) { thisLine += lineTheme(monoutil_1.makeBlank(left - monoutil_1.consoleLn(encBottom))); thisLine += encBottom; } else { thisLine += lineTheme(monoutil_1.makeBlank(this.width - monoutil_1.consoleLn(thisLine))); thisLine += "\n"; thisLine += lineTheme(monoutil_1.makeBlank(this.width - monoutil_1.consoleLn(encBottom))) + encBottom; } } else { thisLine += "\n"; } lastLine = lineNo; out += thisLine; } // out += "\n" return this.write(out.toString()); } /** * Get Header of logger * * [Timestamp] [Header] [typeInfo] * @param header To print header * @param typeStr To print type */ getHeader(header, timeTheme) { const headerCut = monoutil_1.substrMono(header, 0, this.headerSize); const padLn = headerCut.content.length + this.headerSize - monoutil_1.consoleLn(headerCut.original); return `${timeTheme(" " + this.timestamp + " ")} ${headerCut.content.padStart(padLn)}`; } getMiddle(style, typeStr) { const cutted = monoutil_1.substrMono(typeStr, 0, this.headerSize); return style(`${cutted.content.padStart(cutted.content.length + this.middleSize - cutted.original.length + 1)} `); } getFooter(encodedCaller) { return ` ${encodedCaller} `; } write(str) { console.log(str); return str; /* return new Promise<string>((res, rej) => { process.stdout.write(str, () => res(stripAnsi(str))) }) */ } } ChocoLog.defaultLevel = loglv_1.LogLv.ALL; exports.ChocoLog = ChocoLog; /** * Get first element of array * * Null if non exists */ function getFirst(arr) { if (arr == null || arr.length < 1) { return null; } else { return arr[0]; } } /** * Css color element to hex color string * @param text css text */ function cssToColor(text) { if (text == null) { return null; } let filter = text; filter = filter.substr(filter.indexOf(":") + 1).trimLeft(); filter = filter.substring(0, filter.lastIndexOf(";")); try { color_1.default(filter); } catch (err) { const org = filter; filter = getFirst(filter.match(/#[A-Fa-f0-9]{1,6}/ig)); if (filter == null) { throw new Error("Unknown color " + org); } } filter = filter.replace(/url\(.+?\)/ig, "").trim(); filter = `#${color_1.default(filter).rgbNumber().toString(16).padStart(6, "0").toUpperCase()}`; return filter; } function regexIndexOf(text, re, i = 0) { const indexInSuffix = text.slice(i).search(re); return indexInSuffix < 0 ? indexInSuffix : indexInSuffix + i; } function useOrigin() { if (process.env.CLOG_ORIGIN === undefined) { return false; } return process.env.CLOG_ORIGIN === "true"; } function toStringStack(stack) { return `${stack.getFunctionName()} (${stack.getFileName()}:${stack.getLineNumber()}:${stack.getColumnNumber()})`; } const chocolog = new ChocoLog("ChocoRoyce"); exports.default = chocolog; //# sourceMappingURL=log.js.map