simple-ascii-chart
Version:
Simple ascii chart generator
372 lines (371 loc) • 17.8 kB
JavaScript
;
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTransformLabel = exports.removeEmptyLines = exports.setFillArea = exports.addThresholds = exports.addBackgroundSymbol = exports.addBorder = exports.addLegend = exports.addYLabel = exports.addXLable = exports.setTitle = void 0;
var constants_1 = require("../constants");
var coords_1 = require("./coords");
var draw_1 = require("./draw");
var settings_1 = require("./settings");
/**
* Adds a title to the graph at the top.
* @param {object} options - Object containing title options.
* @param {string} options.title - The title text.
* @param {Graph} options.graph - The graph array to modify.
* @param {string} options.backgroundSymbol - Background symbol for the graph.
* @param {number} options.plotWidth - Width of the plot.
* @param {number} options.yShift - Vertical shift for positioning.
*/
var setTitle = function (_a) {
var title = _a.title, graph = _a.graph, backgroundSymbol = _a.backgroundSymbol, plotWidth = _a.plotWidth, yShift = _a.yShift, debugMode = _a.debugMode;
graph.unshift((0, coords_1.toEmpty)(plotWidth + yShift + 2, backgroundSymbol));
Array.from(title).forEach(function (letter, index) {
(0, draw_1.drawPosition)({
debugMode: debugMode,
graph: graph,
scaledX: index,
scaledY: 0,
symbol: letter,
});
});
};
exports.setTitle = setTitle;
/**
* Adds an x-axis label centered at the bottom of the graph.
* @param {object} options - Object containing x-label options.
* @param {string} options.xLabel - The x-axis label text.
* @param {Graph} options.graph - The graph array to modify.
* @param {string} options.backgroundSymbol - Background symbol for the graph.
* @param {number} options.plotWidth - Width of the plot.
* @param {number} options.yShift - Vertical shift for positioning.
*/
var addXLable = function (_a) {
var graph = _a.graph, plotWidth = _a.plotWidth, yShift = _a.yShift, backgroundSymbol = _a.backgroundSymbol, xLabel = _a.xLabel, debugMode = _a.debugMode;
var totalWidth = graph[0].length;
var labelLength = (0, coords_1.toArray)(xLabel).length;
var startingPosition = Math.round((totalWidth - labelLength) / 2);
graph.push((0, coords_1.toEmpty)(plotWidth + yShift + 2, backgroundSymbol));
Array.from(xLabel).forEach(function (letter, index) {
(0, draw_1.drawPosition)({
debugMode: debugMode,
graph: graph,
scaledX: startingPosition + index,
scaledY: graph.length - 1,
symbol: letter,
});
});
};
exports.addXLable = addXLable;
/**
* Adds a y-axis label centered on the left side of the graph.
* @param {object} options - Object containing y-label options.
* @param {Graph} options.graph - The graph array to modify.
* @param {string} options.backgroundSymbol - Background symbol for the graph.
* @param {string} options.yLabel - The y-axis label text.
*/
var addYLabel = function (_a) {
var graph = _a.graph, backgroundSymbol = _a.backgroundSymbol, yLabel = _a.yLabel, debugMode = _a.debugMode;
var totalHeight = graph.length;
var labelLength = (0, coords_1.toArray)(yLabel).length;
var startingPosition = Math.round((totalHeight - labelLength) / 2) - 1;
var label = Array.from(yLabel);
graph.forEach(function (line, position) {
line.unshift(backgroundSymbol);
if (position > startingPosition && label[position - startingPosition - 1]) {
(0, draw_1.drawPosition)({
debugMode: debugMode,
graph: graph,
scaledX: 0,
scaledY: position,
symbol: label[position - startingPosition - 1],
});
}
});
};
exports.addYLabel = addYLabel;
/**
* Adds a legend to the specified position on the graph (top, bottom, left, or right).
* @param {object} options - Object containing legend options.
* @param {Graph} options.graph - The graph array to modify.
* @param {Legend} options.legend - Configuration for the legend's position and series.
* @param {string} options.backgroundSymbol - Background symbol for the graph.
* @param {MultiLine} options.input - Input data series for the chart.
* @param {Colors} [options.color] - Color(s) for each series.
* @param {Symbols} [options.symbols] - Custom symbols for the chart.
* @param {boolean} [options.fillArea] - Whether to fill the area below the lines.
*/
var addLegend = function (_a) {
var graph = _a.graph, legend = _a.legend, backgroundSymbol = _a.backgroundSymbol, color = _a.color, symbols = _a.symbols, fillArea = _a.fillArea, input = _a.input, debugMode = _a.debugMode;
var series = Array.isArray(legend.series) ? legend.series : [legend.series];
var legendWidth = 2 + series.reduce(function (acc, label) { return Math.max(acc, (0, coords_1.toArray)(label).length); }, 0);
var _loop_1 = function (i) {
graph.forEach(function (line, lineIndex) {
if (legend.position === 'left') {
line.unshift(backgroundSymbol); // left
series.forEach(function (label, index) {
if (lineIndex !== index)
return;
// get chart symbols for series
var chartSymbols = (0, settings_1.getChartSymbols)(color, index, symbols === null || symbols === void 0 ? void 0 : symbols.chart, input, fillArea);
var reversedLabel = __spreadArray(__spreadArray([
chartSymbols.area,
backgroundSymbol
], __read(Array.from(label)), false), __read(Array(legendWidth - label.length - 2).fill(backgroundSymbol)), false).reverse();
if (reversedLabel[i]) {
// eslint-disable-next-line no-param-reassign
line[0] = reversedLabel[i];
}
});
}
if (legend.position === 'right') {
line.push(backgroundSymbol);
series.forEach(function (label, index) {
// get chart symbols for series
var chartSymbols = (0, settings_1.getChartSymbols)(color, index, symbols === null || symbols === void 0 ? void 0 : symbols.chart, input, fillArea);
var newSymbol = __spreadArray(__spreadArray([
chartSymbols.area,
backgroundSymbol
], __read(Array.from(label)), false), __read(Array(legendWidth - label.length - 2).fill(backgroundSymbol)), false);
if (lineIndex === index) {
// eslint-disable-next-line no-param-reassign
line[line.length - 1] = newSymbol[i];
}
});
}
});
};
for (var i = 0; i < legendWidth; i += 1) {
_loop_1(i);
}
if (legend.position === 'top') {
series.reverse().forEach(function (label, index) {
graph.unshift((0, coords_1.toEmpty)(graph[0].length, backgroundSymbol)); // top
// get chart symbols for series
var chartSymbols = (0, settings_1.getChartSymbols)(color, index, symbols === null || symbols === void 0 ? void 0 : symbols.chart, input, fillArea);
var newSymbol = __spreadArray([chartSymbols.area, backgroundSymbol], __read(Array.from(label)), false);
graph[index].forEach(function (_, symbolIndex) {
if (newSymbol[symbolIndex]) {
(0, draw_1.drawPosition)({
debugMode: debugMode,
graph: graph,
scaledX: symbolIndex,
scaledY: 0,
symbol: newSymbol[symbolIndex],
});
}
});
});
}
if (legend.position === 'bottom') {
series.forEach(function (label, index) {
graph.push((0, coords_1.toEmpty)(graph[0].length, backgroundSymbol)); // bottom
// get chart symbols for series
var chartSymbols = (0, settings_1.getChartSymbols)(color, index, symbols === null || symbols === void 0 ? void 0 : symbols.chart, input, fillArea);
var newSymbol = __spreadArray([chartSymbols.area, backgroundSymbol], __read(Array.from(label)), false);
graph[index].forEach(function (_, symbolIndex) {
if (newSymbol[symbolIndex]) {
(0, draw_1.drawPosition)({
debugMode: debugMode,
graph: graph,
scaledX: symbolIndex,
scaledY: graph.length - 1,
symbol: newSymbol[symbolIndex],
});
}
});
});
}
};
exports.addLegend = addLegend;
/**
* Adds a border around the graph.
* @param {object} options - Object containing border options.
* @param {Graph} options.graph - The graph array to modify.
* @param {string} options.borderSymbol - The symbol to use for the border.
*/
var addBorder = function (_a) {
var graph = _a.graph, borderSymbol = _a.borderSymbol;
graph.forEach(function (line) {
line.unshift(borderSymbol);
line.push(borderSymbol);
});
graph.unshift((0, coords_1.toEmpty)(graph[0].length, borderSymbol));
graph.push((0, coords_1.toEmpty)(graph[0].length, borderSymbol));
};
exports.addBorder = addBorder;
/**
* Fills the background of empty cells in the graph with a specified symbol.
* @param {object} options - Object containing background fill options.
* @param {Graph} options.graph - The graph array to modify.
* @param {string} options.backgroundSymbol - Symbol to fill empty cells with.
* @param {string} options.emptySymbol - Symbol representing empty cells.
*/
var addBackgroundSymbol = function (_a) {
var graph = _a.graph, backgroundSymbol = _a.backgroundSymbol, emptySymbol = _a.emptySymbol, debugMode = _a.debugMode;
graph.forEach(function (line, curr) {
for (var index = 0; index < line.length; index += 1) {
if (line[index] === emptySymbol) {
(0, draw_1.drawPosition)({
debugMode: debugMode,
graph: graph,
scaledX: index,
scaledY: curr,
symbol: backgroundSymbol,
});
}
else
break;
}
});
};
exports.addBackgroundSymbol = addBackgroundSymbol;
/**
* Adds threshold lines to the graph based on specified x or y values.
* @param {object} options - Object containing threshold options.
* @param {Graph} options.graph - The graph array to modify.
* @param {Threshold[]} options.thresholds - Array of threshold objects with x, y, and color.
* @param {object} options.axis - The axis configuration.
* @param {number} options.plotWidth - Width of the plot.
* @param {number} options.plotHeight - Height of the plot.
* @param {number[]} options.expansionX - x-axis range for scaling.
* @param {number[]} options.expansionY - y-axis range for scaling.
*/
var addThresholds = function (_a) {
var graph = _a.graph, thresholds = _a.thresholds, axis = _a.axis, plotWidth = _a.plotWidth, plotHeight = _a.plotHeight, expansionX = _a.expansionX, expansionY = _a.expansionY, debugMode = _a.debugMode;
var mappedThreshold = thresholds.map(function (_a) {
var thresholdX = _a.x, thresholdY = _a.y;
var x = axis.x, y = axis.y;
if (thresholdX) {
x = thresholdX;
}
if (thresholdY) {
y = thresholdY;
}
return [x, y];
});
(0, coords_1.getPlotCoords)(mappedThreshold, plotWidth, plotHeight, expansionX, expansionY).forEach(function (_a, thresholdNumber) {
var _b, _c;
var _d = __read(_a, 2), x = _d[0], y = _d[1];
var _e = __read((0, coords_1.toPlot)(plotWidth, plotHeight)(x, y), 2), scaledX = _e[0], scaledY = _e[1];
if (((_b = thresholds[thresholdNumber]) === null || _b === void 0 ? void 0 : _b.x) && graph[0][scaledX]) {
graph.forEach(function (_, index) {
var _a, _b;
if (graph[index][scaledX]) {
(0, draw_1.drawPosition)({
debugMode: debugMode,
graph: graph,
scaledX: scaledX + 1,
scaledY: index,
symbol: ((_a = thresholds[thresholdNumber]) === null || _a === void 0 ? void 0 : _a.color)
? "".concat((0, settings_1.getAnsiColor)(((_b = thresholds[thresholdNumber]) === null || _b === void 0 ? void 0 : _b.color) || 'ansiRed')).concat(constants_1.CHART.ns, "\u001B[0m")
: constants_1.CHART.ns,
});
}
});
}
if (((_c = thresholds[thresholdNumber]) === null || _c === void 0 ? void 0 : _c.y) && graph[scaledY]) {
graph[scaledY].forEach(function (_, index) {
var _a, _b;
if (graph[scaledY][index]) {
(0, draw_1.drawPosition)({
debugMode: debugMode,
graph: graph,
scaledX: index,
scaledY: scaledY + 1,
symbol: ((_a = thresholds[thresholdNumber]) === null || _a === void 0 ? void 0 : _a.color)
? "".concat((0, settings_1.getAnsiColor)(((_b = thresholds[thresholdNumber]) === null || _b === void 0 ? void 0 : _b.color) || 'ansiRed')).concat(constants_1.CHART.we, "\u001B[0m")
: constants_1.CHART.we,
});
}
});
}
});
};
exports.addThresholds = addThresholds;
/**
* Fills the area below chart symbols with the specified area symbol.
* @param {object} options - Object containing fill options.
* @param {Graph} options.graph - The graph array to modify.
* @param {Symbols['chart']} options.chartSymbols - Chart symbols to use for filling.
*/
var setFillArea = function (_a) {
var graph = _a.graph, chartSymbols = _a.chartSymbols, debugMode = _a.debugMode;
graph.forEach(function (xValues, yIndex) {
xValues.forEach(function (xSymbol, xIndex) {
var _a;
if (xSymbol === (chartSymbols === null || chartSymbols === void 0 ? void 0 : chartSymbols.nse) ||
xSymbol === (chartSymbols === null || chartSymbols === void 0 ? void 0 : chartSymbols.wsn) ||
xSymbol === (chartSymbols === null || chartSymbols === void 0 ? void 0 : chartSymbols.we) ||
xSymbol === (chartSymbols === null || chartSymbols === void 0 ? void 0 : chartSymbols.area)) {
if ((_a = graph[yIndex + 1]) === null || _a === void 0 ? void 0 : _a[xIndex]) {
(0, draw_1.drawPosition)({
debugMode: debugMode,
graph: graph,
scaledX: xIndex,
scaledY: yIndex + 1,
symbol: chartSymbols.area || constants_1.CHART.area,
});
}
}
});
});
};
exports.setFillArea = setFillArea;
/**
* Removes any completely empty lines from the graph.
* @param {object} options - Object containing empty line removal options.
* @param {Graph} options.graph - The graph array to modify.
* @param {string} options.backgroundSymbol - Background symbol for identifying empty lines.
*/
var removeEmptyLines = function (_a) {
var graph = _a.graph, backgroundSymbol = _a.backgroundSymbol;
var elementsToRemove = [];
graph.forEach(function (line, position) {
if (line.every(function (symbol) { return symbol === backgroundSymbol; })) {
elementsToRemove.push(position);
}
if (graph.every(function (currentLine) { return currentLine[0] === backgroundSymbol; })) {
graph.forEach(function (currentLine) { return currentLine.shift(); });
}
});
elementsToRemove.reverse().forEach(function (position) {
graph.splice(position, 1);
});
};
exports.removeEmptyLines = removeEmptyLines;
/**
* Returns a label transformation function using the specified formatter.
* @param {object} options - Object containing formatter options.
* @param {Formatter} [options.formatter] - Formatter function to apply to labels.
* @returns {Formatter} - A formatter function for transforming labels.
*/
var getTransformLabel = function (_a) {
var formatter = _a.formatter;
return function (value, helpers) {
return formatter ? formatter(value, helpers) : (0, settings_1.defaultFormatter)(value, helpers);
};
};
exports.getTransformLabel = getTransformLabel;