UNPKG

ansi-chart

Version:

A lightweight and simple tool for rendering beautiful charts directly in your terminal using only ANSI-compatible ASCII characters. Create bar charts, line graphs, and more with customizable styles, all without external dependencies. Perfect for CLI appli

65 lines 3.31 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.LineChart = void 0; const asciichart_1 = require("asciichart"); const chalk_1 = __importDefault(require("chalk")); class LineChart { constructor(config) { this.config = config; } plot(data, color) { const xArray = Array.isArray(data[0]) ? data.map((v) => v[0]) : data.map((v, i) => i); const yArray = Array.isArray(data[0]) ? data.map((v) => v[1]) : data.map((v) => v); const chart = (0, asciichart_1.plot)(yArray, this.config); const fullWidth = chart.split('\n')[0].length; const reservedYLegendWidth = chart.split('\n')[0].split(/┤|┼╮|┼/)[0].length + 2; const widthXaxis = fullWidth - reservedYLegendWidth; const longestXLabel = xArray.map((l) => l.toString().length).sort((a, b) => b - a)[0]; const maxDecimals = xArray.map((l) => this.countDecimals(l)).sort((a, b) => b - a)[0]; const maxNoXLabels = Math.floor(widthXaxis / (longestXLabel + 2)); const valueBetweenLabels = (xArray[xArray.length - 1] - xArray[0]) / (maxNoXLabels - 2); const factor = Math.pow(10, maxDecimals); const labels = [Math.round(xArray[0] * factor) / factor]; for (let i = 0; i < maxNoXLabels - 2; ++i) { labels.push(Math.round((labels[labels.length - 1] + valueBetweenLabels) * factor) / factor); } const ticks = this.generateXAxisTicks(widthXaxis, reservedYLegendWidth, xArray, labels); const { xLabel, yLabel } = this.config; console.log(`\t(${yLabel})\n${chalk_1.default.hex(color)(chart)}\n${ticks} (${xLabel})\n`); } generateXAxisTicks(xAxisWidth, yAxisWidth, xArray, labels) { const tickPositions = labels.map((value) => Math.round(((value - xArray[0]) / (xArray[xArray.length - 1] - xArray[0])) * xAxisWidth)); const tickString = [...new Array(yAxisWidth)].join(' ') + [...new Array(xAxisWidth)].map((v, i) => (tickPositions.indexOf(i) > -1 ? '┬' : '─')).join(''); const tickLabelStartPosition = tickPositions.map((pos, i) => pos - Math.floor(labels[i].toString().length / 2)); const reservedWhitespace = [...new Array(yAxisWidth - 1)] .map((v, i) => { if (i - yAxisWidth + 1 == tickLabelStartPosition[0]) return labels[0]; else return ' '; }) .join(''); const startIndex = reservedWhitespace.length + 1 - yAxisWidth; const tickLabels = []; for (let i = startIndex; i < xAxisWidth; ++i) { if (tickLabelStartPosition.indexOf(i) > -1) { tickLabels.push(labels[tickLabelStartPosition.indexOf(i)]); i = startIndex + tickLabels.join('').length - 1; } else tickLabels.push(' '); } return `${tickString}\n${reservedWhitespace + tickLabels.join('')}`; } countDecimals(value) { if (value % 1 != 0) return value.toString().split('.')[1].length; return 0; } } exports.LineChart = LineChart; //# sourceMappingURL=line-chart.js.map