import { pathDesktop } from "./_internal/_global"; import createPath from "./createPath"; import map from "./lodash/#map"; import isArray from "./lodash/basic/isArray"; import templateString from "./templateString"; import writeFile from "./writeFile"; import forEach from "./lodash/#forEach"; import forOwn from "./lodash/#forOwn"; import isDate from "./lodash/#isDate"; import isString from "./lodash/#isString"; function concatJson(head: string, partial: Array, gap: string, mind: string, tail: string): string { return gap ? head + "\n" + gap + partial.join(",\n" + gap) + "\n" + mind + tail : head + partial.join(",") + tail; } function concatSpaceIndent(n: number): string { let indent = "", index = -1; while (++index < n) { indent += " "; } return indent; } function getPrimitiveValue(value: any): any { return isDate(value) ? value.toString() : value.valueOf(); } function stringifyLog(value: any, indent: number | string = 4): string { return stringifyValue(value, isString(indent) ? indent : concatSpaceIndent(indent), ""); } function stringifyArray(array: Array, indent: string, gap: string): string { const mind = gap; gap += indent; let partial: Array = []; forEach(array, (value, index) => { partial[index] = stringifyValue(value, indent, gap); }); return partial.length === 0 ? "[]" : concatJson("[", partial, gap, mind, "]"); } function stringifyObject(object: AnyObject, indent: string, gap: string): string { const mind = gap; gap += indent; const colon = gap ? ": " : ":"; let partial: Array = []; forOwn(object, (value, key) => { partial.push(key + colon + stringifyValue(value, indent, gap)); }); return partial.length === 0 ? "{}" : concatJson("{", partial, gap, mind, "}"); } function stringifyValue(value: any, indent: string, gap: string): string { if (value == null) { return "null"; } const primitive = getPrimitiveValue(value); switch (typeof primitive) { case "string": return "'" + primitive + "'"; case "number": return String(primitive); case "boolean": return String(primitive); case "object": return isArray(primitive) ? stringifyArray(primitive, indent, gap) : stringifyObject(primitive, indent, gap); case "function": return '"' + primitive.toString() + '"'; default: return String(primitive); } } function formatArrayItemLog(item: any, index: number) { return templateString("${0}: ${1}", String(index), stringifyLog(item)); } function formatArrayLog(array: Array) { const source = array.toSource(); const title = source.length > 200 ? "[...]" : source; return templateString(">(${0})", String(array.length)) + title + "\n" + map(array, formatArrayItemLog).join("\n"); } /** * 调试工具。将任意值换行写入到桌面 soil_log.txt 文件中。 * * @param {*} value * @param {?boolean} [rawMode] 启用原始模式,启用后不对输出进行格式化。 * @returns {string} * @since 0.1.0 * @category Soil * @see {@linkcode logJson} * @example * * ```ts * _.log("Hello After Effects!"); * // 桌面日志记录字符串 'Hello After Effects!'。 * * _.log(1); * // 桌面日志记录字符串 '1'。 * * _.log([1, 2, 3]); * // 桌面日志换行记录字符串 '1', '2', '3'。 * * _.log([1, 2, 3], true); * // 桌面日志记录字符串 '1', '2', '3'。 * ``` */ function log(value: any, rawMode?: boolean): string { const content = !rawMode && isArray(value) ? formatArrayLog(value) : stringifyLog(value); const logFile = createPath(pathDesktop.toString(), "soil_log.txt"); writeFile(logFile, content + "\n", undefined, "a"); return content; } export default log;