From 564442542918aeb5c5c5710663c0c28aea9a89f4 Mon Sep 17 00:00:00 2001 From: Tal Hayut Date: Wed, 1 May 2024 10:14:25 +0300 Subject: [PATCH 01/18] chore: refactor the f*** out of chartscii --- consts/defaultOptions.js | 23 ++--- index.js | 205 +++++++++++++++++---------------------- utils.js | 5 + 3 files changed, 101 insertions(+), 132 deletions(-) create mode 100644 utils.js diff --git a/consts/defaultOptions.js b/consts/defaultOptions.js index f1e609c..e21c191 100644 --- a/consts/defaultOptions.js +++ b/consts/defaultOptions.js @@ -6,24 +6,15 @@ module.exports = { color: '', label: '', labels: true, - char: { - value: '█', - default: true - }, - fill: { - value: '░', - default: false - }, + char: '█', + // fill: '░', naked: false, width: 100, theme: '', structure: { - value: { - y: '╢', - x: '══', - leftCorner: '╚', - noLabelChar: '║' - }, - default: true - } + y: '╢', + x: '══', + leftCorner: '╚', + noLabelChar: '║' + }, }; diff --git a/index.js b/index.js index 1509f98..4c88698 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,6 @@ const style = require('styl3'); const defaultOptions = require('./consts/defaultOptions'); +const { getPointValue } = require('./utils'); class Chartscii { constructor(data, options) { @@ -15,34 +16,9 @@ class Chartscii { this.createGraphAxis(); } - defaultOption(option, options) { - if (defaultOptions[option].default || options[option]) { - return defaultOptions[option].value; - } else { - return false; - } - } - setOptions(options = {}) { - const config = Object.keys(defaultOptions).reduce((acc, key) => { - acc[key] = - typeof defaultOptions[key] === 'object' - ? this.defaultOption(key, options) - : defaultOptions[key]; - return acc; - }, {}); - - return Object.keys(options).reduce((acc, option) => { - if ( - typeof options[option] === 'boolean' && - typeof acc[option] === 'string' - ) { - return acc; - } else { - acc[option] = options[option]; - } - return acc; - }, config); + const newOptions = { ...defaultOptions, ...options }; + return newOptions; } sortData(data, reverse) { @@ -55,22 +31,13 @@ class Chartscii { return data; } - getTotal() { - let total = 0; - return ( - total || - function (data) { - return data.reduce((a, p) => { - a += p.value === 0 || p.value ? p.value : p; - return a; - }, total); - } - ); + getTotal(data) { + return data.reduce((a, p) => a += getPointValue(p), 0); } getPercentageData(value, label = undefined) { - const total = this.getTotal(); - const avg = value / total(this.data); + const total = this.getTotal(this.data); + const avg = value / total; const percentage = `${(avg * 100).toFixed(1)}%`; return `${label || value} (${percentage})`; } @@ -104,93 +71,103 @@ class Chartscii { } createGraphAxis() { - this.maxCount += this.data.reduce((acc, point) => { - const value = typeof point === 'object' ? point.value : point; - return value + acc; - }, 0); + this.maxCount += this.getTotal(this.data); this.maxSpace = this.maxLabelLength> 0 ? this.maxLabelLength : 1; const lines = this.data.map((point) => this.line(point)); for (const point of lines) { - const value = point.value || point; - + const value = getPointValue(point); + const color = point.color || this.options.color; + if (!point.label) { - const space = this.maxLabelLength - point.labelColorLess; - let char = this.options.naked - ? `${' '.repeat(space)}${value} ` - : `${' '.repeat(space)}${value} ${this.options.structure.y}`; - if (this.options.labels === false) { - char = this.options.naked - ? `${' '.repeat(space + value.length)}` - : `${' '.repeat(space + value.length)} ${ - this.options.structure.noLabelChar - }`; - } - const color = point.color || this.options.color; - this.chart.push({ key: char, value: value, color }); + const key = this.formatLabelessLine(point, value); + this.chart.push({ key, value, color }); } else { - const space = - this.maxLabelLength - (point.labelColorLess || point.label.length); - const key = this.options.naked - ? `${' '.repeat(space)}${point.label} ` - : `${' '.repeat(space)}${point.label} ${this.options.structure.y}`; - const color = point.color || this.options.color; - const label = point.label; - this.chart.push({ key, value, color, label }); + const key = this.formatLabelLine(point); + this.chart.push({ key, ...point, value }); } } return this.chart; } + formatLabelessLine(point, value) { + const space = this.maxLabelLength - point.labelColorLess; + if (this.options.labels !== false) { + return this.options.naked + ? `${' '.repeat(space)}${value} ` + : `${' '.repeat(space)}${value} ${this.options.structure.y}`; + } + + return this.options.naked + ? `${' '.repeat(space + value.length)}` + : `${' '.repeat(space + value.length)} ${this.options.structure.noLabelChar + }`; + } + + formatLabelLine(point) { + const space = this.maxLabelLength - (point.labelColorLess || point.label.length); + return this.options.naked + ? `${' '.repeat(space)}${point.label} ` + : `${' '.repeat(space)}${point.label} ${this.options.structure.y}`; + } + line(point) { - let value = typeof point === 'object' ? point.value : point; - let label = point.label; + const label = point.label; + const rawValue = getPointValue(point); + const value = rawValue === 0 ? rawValue.toString() : rawValue - this.maxNumeric = this.updateMaxNumeric(value); + this.maxNumeric = this.updateMaxNumeric(rawValue); - if (point.toString() === '0' || point.value === 0) { - value = value.toString(); + if (label) { + return this.makeLabelPoint(point) } - const color = point.color || this.options.color; + return this.makeValuePoint({ ...point, value }); - if (label) { - this.maxLabelLength = this.updateMaxLabelLength(point.label); - point.labelColorLess = point.label.length; + } - if (this.options.percentage) { - point.label = this.getPercentageData(value, label); - point.labelColorLess = point.label.length; - this.maxLabelLength = this.updateMaxLabelLength(point.label); - } + makeLabelPoint(point) { + const value = typeof point === 'object' ? point.value : point; + const color = point.color || this.options.color; + const label = point.label; - if (this.options.colorLabels) { - point.label = this.colorLabel(point.label, color); - } + this.maxLabelLength = this.updateMaxLabelLength(point.label); + point.labelColorLess = point.label.length; - return point; + if (this.options.percentage) { + point.label = this.getPercentageData(value, label); + point.labelColorLess = point.label.length; + this.maxLabelLength = this.updateMaxLabelLength(point.label); } - if (value) { - const point = value.value ? { value: value.value } : { value }; - let labelColorLess = point.value.toString().length; - this.maxLabelLength = this.updateMaxLabelLength(point.value.toString()); + if (this.options.colorLabels) { + point.label = this.colorLabel(point.label, color); + } - if (this.options.percentage) { - point.label = this.getPercentageData(value); - this.maxLabelLength = this.updateMaxLabelLength(point.label); - labelColorLess = point.label.length; - } + return point; + } - if (this.options.colorLabels) { - const printValue = point.label || point.value || point; - point.label = this.colorLabel(printValue, color); - } + makeValuePoint(point) { + const color = point.color || this.options.color; + const value = getPointValue(point); + + let labelColorLess = value.toString().length; + this.maxLabelLength = this.updateMaxLabelLength(value.toString()); + + if (this.options.percentage) { + point.label = this.getPercentageData(value); + this.maxLabelLength = this.updateMaxLabelLength(point.label); + labelColorLess = point.label.length; + } - return { value: point.value, label: point.label, labelColorLess, color }; + if (this.options.colorLabels) { + const printValue = point.label || value; + point.label = this.colorLabel(printValue, color); } + + return { value, label: point.label, labelColorLess, color }; } sortSmallToLarge(arr) { @@ -200,9 +177,8 @@ class Chartscii { } if (a.value) { return a.value - b.value; - } else { - return a - b; } + return a - b; }); return sorted; @@ -225,12 +201,8 @@ class Chartscii { create() { let asciiGraph = this.options.labels - ? `${' '.repeat(this.maxLabelLength + 1)}${ - this.options.structure.leftCorner - }` - : `${' '.repeat(this.maxLabelLength> 1 ? this.maxLabelLength - 1 : this.maxLabelLength)}${ - this.options.structure.leftCorner - }`; + ? `${' '.repeat(this.maxLabelLength + 1)}${this.options.structure.leftCorner}` + : `${' '.repeat(this.maxLabelLength> 1 ? this.maxLabelLength - 1 : this.maxLabelLength)}${this.options.structure.leftCorner}`; asciiGraph = asciiGraph + this.options.structure.x.repeat((this.width / 2)); @@ -244,24 +216,23 @@ class Chartscii { ? this.options.fill.repeat(scaledMaxNumeric - scaledValue) : ''; const color = point.color || this.options.color; - + asciiGraph = color ? `${point.key}${this.colorify( - `${this.options.char.repeat(scaledValue)}${fill}`, - color - )}\n${asciiGraph}` + `${this.options.char.repeat(scaledValue)}${fill}`, + color + )}\n${asciiGraph}` : `${point.key}${this.options.char.repeat( - scaledValue - )}${fill}\n${asciiGraph}`; + scaledValue + )}${fill}\n${asciiGraph}`; }); if (this.options.label) { const space = ' '.repeat(this.maxSpace + 1); const chart = `${space}\n${asciiGraph}`; asciiGraph = this.options.color - ? `${this.colorify(this.options.label, this.options.color)}${ - this.colors.colors.reset - }${chart}` + ? `${this.colorify(this.options.label, this.options.color)}${this.colors.colors.reset + }${chart}` : `${this.options.label}${chart}`; } @@ -278,3 +249,5 @@ class Chartscii { } module.exports = Chartscii; + + diff --git a/utils.js b/utils.js new file mode 100644 index 0000000..a069109 --- /dev/null +++ b/utils.js @@ -0,0 +1,5 @@ +function getPointValue(point) { + return typeof point === "object" ? point.value : point; +} + +module.exports = { getPointValue } \ No newline at end of file From 9d18f0958a32157b78be32198af92c06c074b10b Mon Sep 17 00:00:00 2001 From: Tal Hayut Date: Wed, 1 May 2024 10:46:38 +0300 Subject: [PATCH 02/18] chore: further refactor --- index.js | 42 ++++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/index.js b/index.js index 4c88698..37b23bd 100644 --- a/index.js +++ b/index.js @@ -95,9 +95,7 @@ class Chartscii { formatLabelessLine(point, value) { const space = this.maxLabelLength - point.labelColorLess; if (this.options.labels !== false) { - return this.options.naked - ? `${' '.repeat(space)}${value} ` - : `${' '.repeat(space)}${value} ${this.options.structure.y}`; + return this.formatLine(space, value); } return this.options.naked @@ -108,9 +106,13 @@ class Chartscii { formatLabelLine(point) { const space = this.maxLabelLength - (point.labelColorLess || point.label.length); + return this.formatLine(space, point.label); + } + + formatLine(space, value) { return this.options.naked - ? `${' '.repeat(space)}${point.label} ` - : `${' '.repeat(space)}${point.label} ${this.options.structure.y}`; + ? `${' '.repeat(space)}${value} ` + : `${' '.repeat(space)}${value} ${this.options.structure.y}`; } line(point) { @@ -201,38 +203,26 @@ class Chartscii { create() { let asciiGraph = this.options.labels - ? `${' '.repeat(this.maxLabelLength + 1)}${this.options.structure.leftCorner}` - : `${' '.repeat(this.maxLabelLength> 1 ? this.maxLabelLength - 1 : this.maxLabelLength)}${this.options.structure.leftCorner}`; + ? ' '.repeat(this.maxLabelLength + 1) + this.options.structure.leftCorner + : ' '.repeat(this.maxLabelLength> 1 ? this.maxLabelLength - 1 : this.maxLabelLength) + this.options.structure.leftCorner; asciiGraph = asciiGraph + this.options.structure.x.repeat((this.width / 2)); - this.chart.map((point) => { - const graphValue = point.value; - - const scaledValue = this.getScaledValue(graphValue); - const scaledMaxNumeric = this.width; - - const fill = this.options.fill - ? this.options.fill.repeat(scaledMaxNumeric - scaledValue) - : ''; + for (const point of this.chart) { const color = point.color || this.options.color; + const scaledValue = this.getScaledValue(point.value); + const fill = this.options.fill ? this.options.fill.repeat(this.width - scaledValue) : ''; asciiGraph = color - ? `${point.key}${this.colorify( - `${this.options.char.repeat(scaledValue)}${fill}`, - color - )}\n${asciiGraph}` - : `${point.key}${this.options.char.repeat( - scaledValue - )}${fill}\n${asciiGraph}`; - }); + ? `${point.key}${this.colorify(`${this.options.char.repeat(scaledValue)}${fill}`, color)}\n${asciiGraph}` + : `${point.key}${this.options.char.repeat(scaledValue)}${fill}\n${asciiGraph}`; + } if (this.options.label) { const space = ' '.repeat(this.maxSpace + 1); const chart = `${space}\n${asciiGraph}`; asciiGraph = this.options.color - ? `${this.colorify(this.options.label, this.options.color)}${this.colors.colors.reset - }${chart}` + ? `${this.colorify(this.options.label, this.options.color)}${this.colors.colors.reset}${chart}` : `${this.options.label}${chart}`; } From 537dd9fd905d03109b984226345e80813ce92a1b Mon Sep 17 00:00:00 2001 From: Tal Hayut Date: Wed, 1 May 2024 11:11:58 +0300 Subject: [PATCH 03/18] chore: refactoring create --- index.js | 39 +++++--- index.test.js | 38 ++++---- snapshots/index.test.json | 198 +++++++++++++++++++------------------- 3 files changed, 145 insertions(+), 130 deletions(-) diff --git a/index.js b/index.js index 37b23bd..618206d 100644 --- a/index.js +++ b/index.js @@ -201,34 +201,49 @@ class Chartscii { } } - create() { - let asciiGraph = this.options.labels + makeChartLabel() { + if (this.options.label) { + const space = ' '.repeat(this.maxSpace + 1); + return this.options.color + ? `${this.colorify(this.options.label, this.options.color)}${this.colors.colors.reset}${space}` + : `${this.options.label}${space}`; + } + + return ''; + } + + makeChartBottom() { + const base = this.options.labels ? ' '.repeat(this.maxLabelLength + 1) + this.options.structure.leftCorner : ' '.repeat(this.maxLabelLength> 1 ? this.maxLabelLength - 1 : this.maxLabelLength) + this.options.structure.leftCorner; - asciiGraph = asciiGraph + this.options.structure.x.repeat((this.width / 2)); + return base + this.options.structure.x.repeat((this.width / 2)) + } + + create() { + const asciiChart = []; for (const point of this.chart) { const color = point.color || this.options.color; const scaledValue = this.getScaledValue(point.value); const fill = this.options.fill ? this.options.fill.repeat(this.width - scaledValue) : ''; + const line = color + ? `${point.key}${this.colorify(`${this.options.char.repeat(scaledValue)}${fill}`, color)}` + : `${point.key}${this.options.char.repeat(scaledValue)}${fill}` - asciiGraph = color - ? `${point.key}${this.colorify(`${this.options.char.repeat(scaledValue)}${fill}`, color)}\n${asciiGraph}` - : `${point.key}${this.options.char.repeat(scaledValue)}${fill}\n${asciiGraph}`; + asciiChart.push(line); } if (this.options.label) { - const space = ' '.repeat(this.maxSpace + 1); - const chart = `${space}\n${asciiGraph}`; - asciiGraph = this.options.color - ? `${this.colorify(this.options.label, this.options.color)}${this.colors.colors.reset}${chart}` - : `${this.options.label}${chart}`; + asciiChart.push(this.makeChartLabel()); } - return asciiGraph; + asciiChart.push(this.makeChartBottom()) + return asciiChart.join('\n'); } + + getScaledValue(value) { return Math.round((value / this.maxNumeric) * this.width); } diff --git a/index.test.js b/index.test.js index 122dab9..f1776d8 100644 --- a/index.test.js +++ b/index.test.js @@ -3,23 +3,23 @@ const expect = chai.expect; const Chartscii = require('./index'); const snap = require('snaptdout'); const colors = [ - 'red', - 'green', - 'yellow', - 'blue', - 'purple', - 'pink', - 'cyan', - 'orange', - ]; + 'red', + 'green', + 'yellow', + 'blue', + 'purple', + 'pink', + 'cyan', + 'orange', +]; function generateChartData() { - const data = []; - for (let i = 0; i < colors.length; i++) { - const color = colors[i]; - data.push({ value: i + 1, label: color, color }); - } - return data; + const data = []; + for (let i = 0; i < colors.length; i++) { + const color = colors[i]; + data.push({ value: i + 1, label: color, color }); + } + return data; } describe('chartscii tests', () => { @@ -91,13 +91,13 @@ describe('examples', () => { }); await snap(chart.create(), 'percentage'); }); - + it('should support labeless chart', async () => { const data = []; for (let i = 0; i < 20; i++) { data.push(i + 1); } - const chart = new Chartscii(data, {labels: false}); + const chart = new Chartscii(data, { labels: false }); await snap(chart.create(), 'labeless chart'); }); @@ -107,7 +107,7 @@ describe('examples', () => { const color = colors[i]; data.push({ value: i + 1, color }); } - const chart = new Chartscii(data, {labels: false}); + const chart = new Chartscii(data, { labels: false }); await snap(chart.create(), 'labeless color chart'); }); @@ -133,7 +133,7 @@ describe('examples', () => { }); it('should support default theme', async () => { const data = generateChartData(); - const chart = new Chartscii(data, {colorLabels: true}); + const chart = new Chartscii(data, { colorLabels: true }); await snap(chart.create(), 'default theme'); }); diff --git a/snapshots/index.test.json b/snapshots/index.test.json index 68148a1..4c07366 100644 --- a/snapshots/index.test.json +++ b/snapshots/index.test.json @@ -1,137 +1,137 @@ { "chart": [ - "\u001b[38;5;219mlabel 19\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 18\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 17\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 16\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 15\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 14\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 13\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 12\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 11\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 10\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 9\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 8\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 7\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 6\u001b[0m ╢\u001b[38;5;219m████████████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 5\u001b[0m ╢\u001b[38;5;219m██████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 4\u001b[0m ╢\u001b[38;5;219m█████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 3\u001b[0m ╢\u001b[38;5;219m████████████████\u001b[0m", - " \u001b[38;5;219mlabel 2\u001b[0m ╢\u001b[38;5;219m███████████\u001b[0m", - " \u001b[38;5;219mlabel 1\u001b[0m ╢\u001b[38;5;219m█████\u001b[0m", " \u001b[38;5;219mlabel 0\u001b[0m ╢\u001b[38;5;219m\u001b[0m", + " \u001b[38;5;219mlabel 1\u001b[0m ╢\u001b[38;5;219m█████\u001b[0m", + " \u001b[38;5;219mlabel 2\u001b[0m ╢\u001b[38;5;219m███████████\u001b[0m", + " \u001b[38;5;219mlabel 3\u001b[0m ╢\u001b[38;5;219m████████████████\u001b[0m", + " \u001b[38;5;219mlabel 4\u001b[0m ╢\u001b[38;5;219m█████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 5\u001b[0m ╢\u001b[38;5;219m██████████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 6\u001b[0m ╢\u001b[38;5;219m████████████████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 7\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 8\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 9\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 10\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 11\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 12\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 13\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 14\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 15\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 16\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 17\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 18\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 19\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" ], "percentage": [ - "\u001b[38;5;219mlabel 19 (9.5%)\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 18 (9.0%)\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 17 (8.6%)\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 16 (8.1%)\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 15 (7.6%)\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 14 (7.1%)\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 13 (6.7%)\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 12 (6.2%)\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 11 (5.7%)\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 10 (5.2%)\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 9 (4.8%)\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 8 (4.3%)\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 7 (3.8%)\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 6 (3.3%)\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 5 (2.9%)\u001b[0m ╢\u001b[38;5;219m██████████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 4 (2.4%)\u001b[0m ╢\u001b[38;5;219m█████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 3 (1.9%)\u001b[0m ╢\u001b[38;5;219m████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 2 (1.4%)\u001b[0m ╢\u001b[38;5;219m███████████████\u001b[0m", - " \u001b[38;5;219mlabel 1 (1.0%)\u001b[0m ╢\u001b[38;5;219m██████████\u001b[0m", " \u001b[38;5;219mlabel 0 (0.5%)\u001b[0m ╢\u001b[38;5;219m█████\u001b[0m", + " \u001b[38;5;219mlabel 1 (1.0%)\u001b[0m ╢\u001b[38;5;219m██████████\u001b[0m", + " \u001b[38;5;219mlabel 2 (1.4%)\u001b[0m ╢\u001b[38;5;219m███████████████\u001b[0m", + " \u001b[38;5;219mlabel 3 (1.9%)\u001b[0m ╢\u001b[38;5;219m████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 4 (2.4%)\u001b[0m ╢\u001b[38;5;219m█████████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 5 (2.9%)\u001b[0m ╢\u001b[38;5;219m██████████████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 6 (3.3%)\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 7 (3.8%)\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 8 (4.3%)\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 9 (4.8%)\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 10 (5.2%)\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 11 (5.7%)\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 12 (6.2%)\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 13 (6.7%)\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 14 (7.1%)\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 15 (7.6%)\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 16 (8.1%)\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 17 (8.6%)\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 18 (9.0%)\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 19 (9.5%)\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" ], "labeless chart": [ - " ║████████████████████████████████████████████████████████████████████████████████████████████████████", - " ║███████████████████████████████████████████████████████████████████████████████████████████████", - " ║██████████████████████████████████████████████████████████████████████████████████████████", - " ║█████████████████████████████████████████████████████████████████████████████████████", - " ║████████████████████████████████████████████████████████████████████████████████", - " ║███████████████████████████████████████████████████████████████████████████", - " ║██████████████████████████████████████████████████████████████████████", - " ║█████████████████████████████████████████████████████████████████", - " ║████████████████████████████████████████████████████████████", - " ║███████████████████████████████████████████████████████", - " ║██████████████████████████████████████████████████", - " ║█████████████████████████████████████████████", - " ║████████████████████████████████████████", - " ║███████████████████████████████████", - " ║██████████████████████████████", - " ║█████████████████████████", - " ║████████████████████", - " ║███████████████", - " ║██████████", " ║█████", + " ║██████████", + " ║███████████████", + " ║████████████████████", + " ║█████████████████████████", + " ║██████████████████████████████", + " ║███████████████████████████████████", + " ║████████████████████████████████████████", + " ║█████████████████████████████████████████████", + " ║██████████████████████████████████████████████████", + " ║███████████████████████████████████████████████████████", + " ║████████████████████████████████████████████████████████████", + " ║█████████████████████████████████████████████████████████████████", + " ║██████████████████████████████████████████████████████████████████████", + " ║███████████████████████████████████████████████████████████████████████████", + " ║████████████████████████████████████████████████████████████████████████████████", + " ║█████████████████████████████████████████████████████████████████████████████████████", + " ║██████████████████████████████████████████████████████████████████████████████████████████", + " ║███████████████████████████████████████████████████████████████████████████████████████████████", + " ║████████████████████████████████████████████████████████████████████████████████████████████████████", " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" ], "labeless color chart": [ - " ║\u001b[38;5;215m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " ║\u001b[96m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " ║\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", - " ║\u001b[35m███████████████████████████████████████████████████████████████\u001b[0m", - " ║\u001b[34m██████████████████████████████████████████████████\u001b[0m", - " ║\u001b[38;5;227m██████████████████████████████████████\u001b[0m", - " ║\u001b[32m█████████████████████████\u001b[0m", " ║\u001b[38;5;160m█████████████\u001b[0m", + " ║\u001b[32m█████████████████████████\u001b[0m", + " ║\u001b[38;5;227m██████████████████████████████████████\u001b[0m", + " ║\u001b[34m██████████████████████████████████████████████████\u001b[0m", + " ║\u001b[35m███████████████████████████████████████████████████████████████\u001b[0m", + " ║\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", + " ║\u001b[96m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + " ║\u001b[38;5;215m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" ], "pastel theme": [ - "\u001b[38;5;209morange\u001b[0m ╢\u001b[38;5;209m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;159mcyan\u001b[0m ╢\u001b[38;5;159m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;219mpink\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;147mpurple\u001b[0m ╢\u001b[38;5;147m███████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;39mblue\u001b[0m ╢\u001b[38;5;39m██████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;228myellow\u001b[0m ╢\u001b[38;5;228m██████████████████████████████████████\u001b[0m", - " \u001b[38;5;49mgreen\u001b[0m ╢\u001b[38;5;49m█████████████████████████\u001b[0m", " \u001b[31mred\u001b[0m ╢\u001b[31m█████████████\u001b[0m", + " \u001b[38;5;49mgreen\u001b[0m ╢\u001b[38;5;49m█████████████████████████\u001b[0m", + "\u001b[38;5;228myellow\u001b[0m ╢\u001b[38;5;228m██████████████████████████████████████\u001b[0m", + " \u001b[38;5;39mblue\u001b[0m ╢\u001b[38;5;39m██████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;147mpurple\u001b[0m ╢\u001b[38;5;147m███████████████████████████████████████████████████████████████\u001b[0m", + " \u001b[38;5;219mpink\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", + " \u001b[38;5;159mcyan\u001b[0m ╢\u001b[38;5;159m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;209morange\u001b[0m ╢\u001b[38;5;209m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" ], "lush theme": [ - "\u001b[38;5;202morange\u001b[0m ╢\u001b[38;5;202m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;87mcyan\u001b[0m ╢\u001b[38;5;87m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;198mpink\u001b[0m ╢\u001b[38;5;198m███████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;128mpurple\u001b[0m ╢\u001b[38;5;128m███████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;57mblue\u001b[0m ╢\u001b[38;5;57m██████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;226myellow\u001b[0m ╢\u001b[38;5;226m██████████████████████████████████████\u001b[0m", - " \u001b[38;5;154mgreen\u001b[0m ╢\u001b[38;5;154m█████████████████████████\u001b[0m", " \u001b[38;5;196mred\u001b[0m ╢\u001b[38;5;196m█████████████\u001b[0m", + " \u001b[38;5;154mgreen\u001b[0m ╢\u001b[38;5;154m█████████████████████████\u001b[0m", + "\u001b[38;5;226myellow\u001b[0m ╢\u001b[38;5;226m██████████████████████████████████████\u001b[0m", + " \u001b[38;5;57mblue\u001b[0m ╢\u001b[38;5;57m██████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;128mpurple\u001b[0m ╢\u001b[38;5;128m███████████████████████████████████████████████████████████████\u001b[0m", + " \u001b[38;5;198mpink\u001b[0m ╢\u001b[38;5;198m███████████████████████████████████████████████████████████████████████████\u001b[0m", + " \u001b[38;5;87mcyan\u001b[0m ╢\u001b[38;5;87m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;202morange\u001b[0m ╢\u001b[38;5;202m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" ], "standard theme": [ - "\u001b[38;5;214morange\u001b[0m ╢\u001b[38;5;214m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;123mcyan\u001b[0m ╢\u001b[38;5;123m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;200mpink\u001b[0m ╢\u001b[38;5;200m███████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;105mpurple\u001b[0m ╢\u001b[38;5;105m███████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;27mblue\u001b[0m ╢\u001b[38;5;27m██████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;11myellow\u001b[0m ╢\u001b[38;5;11m██████████████████████████████████████\u001b[0m", - " \u001b[38;5;10mgreen\u001b[0m ╢\u001b[38;5;10m█████████████████████████\u001b[0m", " \u001b[38;5;9mred\u001b[0m ╢\u001b[38;5;9m█████████████\u001b[0m", + " \u001b[38;5;10mgreen\u001b[0m ╢\u001b[38;5;10m█████████████████████████\u001b[0m", + "\u001b[38;5;11myellow\u001b[0m ╢\u001b[38;5;11m██████████████████████████████████████\u001b[0m", + " \u001b[38;5;27mblue\u001b[0m ╢\u001b[38;5;27m██████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;105mpurple\u001b[0m ╢\u001b[38;5;105m███████████████████████████████████████████████████████████████\u001b[0m", + " \u001b[38;5;200mpink\u001b[0m ╢\u001b[38;5;200m███████████████████████████████████████████████████████████████████████████\u001b[0m", + " \u001b[38;5;123mcyan\u001b[0m ╢\u001b[38;5;123m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;214morange\u001b[0m ╢\u001b[38;5;214m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" ], "beach theme": [ - "\u001b[38;2;247;126;2morange\u001b[0m ╢\u001b[38;2;247;126;2m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;2;0;255;255mcyan\u001b[0m ╢\u001b[38;2;0;255;255m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;2;222;82;133mpink\u001b[0m ╢\u001b[38;2;222;82;133m███████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;2;130;119;249mpurple\u001b[0m ╢\u001b[38;2;130;119;249m███████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;2;146;196;238mblue\u001b[0m ╢\u001b[38;2;146;196;238m██████████████████████████████████████████████████\u001b[0m", - "\u001b[38;2;254;215;102myellow\u001b[0m ╢\u001b[38;2;254;215;102m██████████████████████████████████████\u001b[0m", - " \u001b[38;2;42;183;202mgreen\u001b[0m ╢\u001b[38;2;42;183;202m█████████████████████████\u001b[0m", " \u001b[38;2;254;74;73mred\u001b[0m ╢\u001b[38;2;254;74;73m█████████████\u001b[0m", + " \u001b[38;2;42;183;202mgreen\u001b[0m ╢\u001b[38;2;42;183;202m█████████████████████████\u001b[0m", + "\u001b[38;2;254;215;102myellow\u001b[0m ╢\u001b[38;2;254;215;102m██████████████████████████████████████\u001b[0m", + " \u001b[38;2;146;196;238mblue\u001b[0m ╢\u001b[38;2;146;196;238m██████████████████████████████████████████████████\u001b[0m", + "\u001b[38;2;130;119;249mpurple\u001b[0m ╢\u001b[38;2;130;119;249m███████████████████████████████████████████████████████████████\u001b[0m", + " \u001b[38;2;222;82;133mpink\u001b[0m ╢\u001b[38;2;222;82;133m███████████████████████████████████████████████████████████████████████████\u001b[0m", + " \u001b[38;2;0;255;255mcyan\u001b[0m ╢\u001b[38;2;0;255;255m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;2;247;126;2morange\u001b[0m ╢\u001b[38;2;247;126;2m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" ], "default theme": [ - "\u001b[38;5;215morange\u001b[0m ╢\u001b[38;5;215m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[96mcyan\u001b[0m ╢\u001b[96m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;219mpink\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[35mpurple\u001b[0m ╢\u001b[35m███████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[34mblue\u001b[0m ╢\u001b[34m██████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;227myellow\u001b[0m ╢\u001b[38;5;227m██████████████████████████████████████\u001b[0m", - " \u001b[32mgreen\u001b[0m ╢\u001b[32m█████████████████████████\u001b[0m", " \u001b[38;5;160mred\u001b[0m ╢\u001b[38;5;160m█████████████\u001b[0m", + " \u001b[32mgreen\u001b[0m ╢\u001b[32m█████████████████████████\u001b[0m", + "\u001b[38;5;227myellow\u001b[0m ╢\u001b[38;5;227m██████████████████████████████████████\u001b[0m", + " \u001b[34mblue\u001b[0m ╢\u001b[34m██████████████████████████████████████████████████\u001b[0m", + "\u001b[35mpurple\u001b[0m ╢\u001b[35m███████████████████████████████████████████████████████████████\u001b[0m", + " \u001b[38;5;219mpink\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", + " \u001b[96mcyan\u001b[0m ╢\u001b[96m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;215morange\u001b[0m ╢\u001b[38;5;215m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" ] } \ No newline at end of file From 00d1c0b142e0c86b321aefc9b9b642d304489a11 Mon Sep 17 00:00:00 2001 From: Tal Hayut Date: Wed, 1 May 2024 11:41:34 +0300 Subject: [PATCH 04/18] chore: rename some stuff --- consts/defaultOptions.js => config/config.js | 3 ++- index.js | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-) rename consts/defaultOptions.js => config/config.js (94%) diff --git a/consts/defaultOptions.js b/config/config.js similarity index 94% rename from consts/defaultOptions.js rename to config/config.js index e21c191..f4c4d67 100644 --- a/consts/defaultOptions.js +++ b/config/config.js @@ -7,7 +7,6 @@ module.exports = { label: '', labels: true, char: '█', - // fill: '░', naked: false, width: 100, theme: '', @@ -18,3 +17,5 @@ module.exports = { noLabelChar: '║' }, }; + +// fill: '░', \ No newline at end of file diff --git a/index.js b/index.js index 618206d..c6b5dec 100644 --- a/index.js +++ b/index.js @@ -1,14 +1,15 @@ const style = require('styl3'); -const defaultOptions = require('./consts/defaultOptions'); +const defaultOptions = require('./config/config'); const { getPointValue } = require('./utils'); class Chartscii { constructor(data, options) { this.chart = []; this.maxSpace = 1; - this.maxLabelLength = 0; - this.maxNumeric = 0; - this.maxCount = 0; + // this.maxLabelLength = 0; + // this.maxNumeric = 0; + // this.maxCount = 0; + this.measures = { numeric: 0, count: 0, label: 0 } this.options = this.setOptions(options); this.colors = style({ theme: this.options.theme }); this.width = this.options.width; From 8e4ddd4de64ec44e3a4a0d191b14f773a3df66e2 Mon Sep 17 00:00:00 2001 From: Tal Hayut Date: Wed, 1 May 2024 11:45:53 +0300 Subject: [PATCH 05/18] chore: add measures --- index.js | 55 +++++++++++++++++++++++++------------------------------ 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/index.js b/index.js index c6b5dec..761c04e 100644 --- a/index.js +++ b/index.js @@ -5,11 +5,7 @@ const { getPointValue } = require('./utils'); class Chartscii { constructor(data, options) { this.chart = []; - this.maxSpace = 1; - // this.maxLabelLength = 0; - // this.maxNumeric = 0; - // this.maxCount = 0; - this.measures = { numeric: 0, count: 0, label: 0 } + this.measures = { numeric: 0, count: 0, label: 0, space: 1 } this.options = this.setOptions(options); this.colors = style({ theme: this.options.theme }); this.width = this.options.width; @@ -48,13 +44,13 @@ class Chartscii { } updateMaxLabelLength(label) { - return label.length>= this.maxLabelLength + return label.length>= this.measures.label ? label.length - : this.maxLabelLength; + : this.measures.label; } updateMaxNumeric(value) { - return value>= this.maxNumeric ? value : this.maxNumeric; + return value>= this.measures.numeric ? value : this.measures.numeric; } colorify(txt, color) { @@ -72,8 +68,7 @@ class Chartscii { } createGraphAxis() { - this.maxCount += this.getTotal(this.data); - this.maxSpace = this.maxLabelLength> 0 ? this.maxLabelLength : 1; + this.measures.space = this.measures.label> 0 ? this.measures.label : 1; const lines = this.data.map((point) => this.line(point)); @@ -94,7 +89,7 @@ class Chartscii { } formatLabelessLine(point, value) { - const space = this.maxLabelLength - point.labelColorLess; + const space = this.measures.label - point.labelColorLess; if (this.options.labels !== false) { return this.formatLine(space, value); } @@ -106,7 +101,7 @@ class Chartscii { } formatLabelLine(point) { - const space = this.maxLabelLength - (point.labelColorLess || point.label.length); + const space = this.measures.label - (point.labelColorLess || point.label.length); return this.formatLine(space, point.label); } @@ -121,7 +116,7 @@ class Chartscii { const rawValue = getPointValue(point); const value = rawValue === 0 ? rawValue.toString() : rawValue - this.maxNumeric = this.updateMaxNumeric(rawValue); + this.measures.numeric = this.updateMaxNumeric(rawValue); if (label) { return this.makeLabelPoint(point) @@ -136,13 +131,13 @@ class Chartscii { const color = point.color || this.options.color; const label = point.label; - this.maxLabelLength = this.updateMaxLabelLength(point.label); + this.measures.label = this.updateMaxLabelLength(point.label); point.labelColorLess = point.label.length; if (this.options.percentage) { point.label = this.getPercentageData(value, label); point.labelColorLess = point.label.length; - this.maxLabelLength = this.updateMaxLabelLength(point.label); + this.measures.label = this.updateMaxLabelLength(point.label); } if (this.options.colorLabels) { @@ -157,11 +152,11 @@ class Chartscii { const value = getPointValue(point); let labelColorLess = value.toString().length; - this.maxLabelLength = this.updateMaxLabelLength(value.toString()); + this.measures.label = this.updateMaxLabelLength(value.toString()); if (this.options.percentage) { point.label = this.getPercentageData(value); - this.maxLabelLength = this.updateMaxLabelLength(point.label); + this.measures.label = this.updateMaxLabelLength(point.label); labelColorLess = point.label.length; } @@ -188,23 +183,23 @@ class Chartscii { } makeSpace() { - if (this.maxSpace === 2) { - return ' '.repeat(this.maxSpace + 1); + if (this.measures.space === 2) { + return ' '.repeat(this.measures.space + 1); } - if (this.maxSpace % 2 === 0) { - return ' '.repeat(this.maxSpace); - } else if (this.maxSpace % 3 === 0) { - return this.maxSpace === 3 ? ' ' : ' '.repeat(this.maxSpace - 7); - } else if (this.maxSpace < 2) { - return ' '.repeat(this.maxSpace + 1); + if (this.measures.space % 2 === 0) { + return ' '.repeat(this.measures.space); + } else if (this.measures.space % 3 === 0) { + return this.measures.space === 3 ? ' ' : ' '.repeat(this.measures.space - 7); + } else if (this.measures.space < 2) { + return ' '.repeat(this.measures.space + 1); } else { - return ' '.repeat(this.maxSpace - 3); + return ' '.repeat(this.measures.space - 3); } } makeChartLabel() { if (this.options.label) { - const space = ' '.repeat(this.maxSpace + 1); + const space = ' '.repeat(this.measures.space + 1); return this.options.color ? `${this.colorify(this.options.label, this.options.color)}${this.colors.colors.reset}${space}` : `${this.options.label}${space}`; @@ -215,8 +210,8 @@ class Chartscii { makeChartBottom() { const base = this.options.labels - ? ' '.repeat(this.maxLabelLength + 1) + this.options.structure.leftCorner - : ' '.repeat(this.maxLabelLength> 1 ? this.maxLabelLength - 1 : this.maxLabelLength) + this.options.structure.leftCorner; + ? ' '.repeat(this.measures.label + 1) + this.options.structure.leftCorner + : ' '.repeat(this.measures.label> 1 ? this.measures.label - 1 : this.measures.label) + this.options.structure.leftCorner; return base + this.options.structure.x.repeat((this.width / 2)) } @@ -246,7 +241,7 @@ class Chartscii { getScaledValue(value) { - return Math.round((value / this.maxNumeric) * this.width); + return Math.round((value / this.measures.numeric) * this.width); } get() { From cf0223952b1e67b55907d785923483b5b3a0f054 Mon Sep 17 00:00:00 2001 From: Tal Hayut Date: Wed, 1 May 2024 11:53:23 +0300 Subject: [PATCH 06/18] fix: complicated space logic --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 761c04e..a1dd0c1 100644 --- a/index.js +++ b/index.js @@ -68,7 +68,7 @@ class Chartscii { } createGraphAxis() { - this.measures.space = this.measures.label> 0 ? this.measures.label : 1; + this.measures.space = this.measures.label || 1; const lines = this.data.map((point) => this.line(point)); From 0f7457bebac46462184dd6988bddd4bb70c53260 Mon Sep 17 00:00:00 2001 From: Tal Hayut Date: Thu, 2 May 2024 09:55:13 +0300 Subject: [PATCH 07/18] feat: added vertical orientation --- config/config.js | 2 +- index.js | 101 +- package-lock.json | 2298 ++++++++++++++++++++++++++++++++++++++ package.json | 7 +- pp.js | 30 + snapshots/main.test.json | 137 +++ ts/main.test.ts | 140 +++ ts/main.ts | 260 +++++ ts/tsconfig.json | 20 + ts/types.ts | 42 + ts/utils.ts | 9 + utils.js | 10 +- yarn.lock | 527 +++++---- 13 files changed, 3356 insertions(+), 227 deletions(-) create mode 100644 package-lock.json create mode 100644 pp.js create mode 100644 snapshots/main.test.json create mode 100644 ts/main.test.ts create mode 100644 ts/main.ts create mode 100644 ts/tsconfig.json create mode 100644 ts/types.ts create mode 100644 ts/utils.ts diff --git a/config/config.js b/config/config.js index f4c4d67..7caf1a1 100644 --- a/config/config.js +++ b/config/config.js @@ -3,7 +3,7 @@ module.exports = { colorLabels: false, sort: false, reverse: false, - color: '', + color: undefined, label: '', labels: true, char: '█', diff --git a/index.js b/index.js index a1dd0c1..8ad83b7 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ const style = require('styl3'); const defaultOptions = require('./config/config'); -const { getPointValue } = require('./utils'); +const { getPointValue, getPointLabel, padLine } = require('./utils'); class Chartscii { constructor(data, options) { @@ -33,14 +33,18 @@ class Chartscii { } getPercentageData(value, label = undefined) { - const total = this.getTotal(this.data); - const avg = value / total; - const percentage = `${(avg * 100).toFixed(1)}%`; - return `${label || value} (${percentage})`; + if (this.options.percentage) { + const total = this.getTotal(this.data); + const avg = value / total; + const percentage = `${(avg * 100).toFixed(1)}%`; + return `${label || value} (${percentage})`; + } else { + return label || value.toString(); + } } colorLabel(label, color) { - return label.toString().replace(label, this.colorify(label, color)); + return color ? label.toString().replace(label, this.colorify(label, color)) : label; } updateMaxLabelLength(label) { @@ -126,6 +130,63 @@ class Chartscii { } + + verticalChart() { + const maxHeight = Math.max(...this.data.map(d => this.getScaledValue(getPointValue(d)))); + const labelWidths = this.data.map(point => point.labelColorLess); + const maxLabelWidth = Math.max(...labelWidths); + const barWidth = this.options.barWidth || maxLabelWidth; + const verticalChart = Array(maxHeight + 1).fill('').map(() => Array(this.data.length).fill(' ').map(() => ' '.repeat(maxLabelWidth))); + const spaces = []; + + this.data.forEach((point, index) => { + const value = this.getScaledValue(getPointValue(point)); + const height = Math.round((value / maxHeight) * maxHeight); + const percentageLabel = point.label; + + const padding = Math.floor((maxLabelWidth - barWidth) / 2); + const label = percentageLabel.padEnd(maxLabelWidth, ' '); + + for (let i = 0; i < maxHeight; i++) { + if (i < maxHeight - height) { + if (this.options.fill) { + const coloredFillChar = this.options.color ? this.colorify(this.options.fill, this.options.color) : this.options.fill; + verticalChart[i][index] = padLine(padding, coloredFillChar.repeat(barWidth)); + } + } else { + const unevenPadding = barWidth % 2 === 0 ? 1 : 0; + const coloredChar = this.options.color ? this.colorify(this.options.char, this.options.color) : this.options.char; + verticalChart[i][index] = ' '.repeat(padding + unevenPadding) + coloredChar.repeat(barWidth) + ' '.repeat(padding) + } + } + const labelSpace = Math.floor(maxLabelWidth - this.stripAnsi(label).length); + const labelPadding = this.options.colorLabels && labelSpace> 0 ? ' '.repeat(labelSpace) : '' + verticalChart[maxHeight][index] = label + labelPadding; + spaces.push(label + labelPadding) + }); + + const chart = verticalChart.map(row => { + if (!this.options.naked) { + return this.options.structure.y + ' ' + row.join(' ') + } + return row.join(' ') + }) + + if (!this.options.naked) { + const removeSpace = this.options.percentage ? 7 : 3; + const width = (this.stripAnsi(spaces[0]).length - removeSpace) * this.data.length; + chart.push([this.makeVerticalChartBottom(width)]) + } + + chart.unshift([this.makeChartLabel()]) + return chart.join('\n'); + } + + stripAnsi(str) { + return str.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, ''); + } + + makeLabelPoint(point) { const value = typeof point === 'object' ? point.value : point; const color = point.color || this.options.color; @@ -201,8 +262,8 @@ class Chartscii { if (this.options.label) { const space = ' '.repeat(this.measures.space + 1); return this.options.color - ? `${this.colorify(this.options.label, this.options.color)}${this.colors.colors.reset}${space}` - : `${this.options.label}${space}`; + ? this.colorify(this.options.label, this.options.color) + this.colors.colors.reset + space + : this.options.label + space; } return ''; @@ -216,24 +277,36 @@ class Chartscii { return base + this.options.structure.x.repeat((this.width / 2)) } + makeVerticalChartBottom(width = this.width) { + const base = this.options.labels + ? this.options.structure.leftCorner.repeat(1) + : ' '.repeat(this.measures.label> 1 ? this.measures.label - 1 : this.measures.label) + this.options.structure.leftCorner; + + return base + this.options.structure.x.repeat(width) + } + create() { const asciiChart = []; + if (this.options.orientation === 'vertical') { + return this.verticalChart(); + } + + if (this.options.label) { + asciiChart.push(this.makeChartLabel()); + } + for (const point of this.chart) { const color = point.color || this.options.color; const scaledValue = this.getScaledValue(point.value); const fill = this.options.fill ? this.options.fill.repeat(this.width - scaledValue) : ''; const line = color - ? `${point.key}${this.colorify(`${this.options.char.repeat(scaledValue)}${fill}`, color)}` - : `${point.key}${this.options.char.repeat(scaledValue)}${fill}` + ? point.key + this.colorify(this.options.char.repeat(scaledValue) + fill, color) + : point.key + this.options.char.repeat(scaledValue) + fill asciiChart.push(line); } - if (this.options.label) { - asciiChart.push(this.makeChartLabel()); - } - asciiChart.push(this.makeChartBottom()) return asciiChart.join('\n'); } diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..46999d2 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2298 @@ +{ + "name": "chartscii", + "version": "1.3.2", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "chartscii", + "version": "1.3.2", + "license": "MIT", + "dependencies": { + "styl3": "^1.2.4" + }, + "devDependencies": { + "@types/chai": "4.3.14", + "@types/mocha": "10.0.6", + "chai": "4.2.0", + "husky": "8.0.3", + "mocha": "^10.0.0", + "shellfie": "^1.3.1", + "snaptdout": "^2.1.0", + "ts-node": "10.9.2", + "typescript": "5.4.5" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@puppeteer/browsers": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.9.1.tgz", + "integrity": "sha512-PuvK6xZzGhKPvlx3fpfdM2kYY3P/hB1URtK8wA7XUJ6prn6pp22zvJHu48th0SGcHL9SutbPHrFuQgfXTFobWA==", + "dev": true, + "dependencies": { + "debug": "4.3.4", + "extract-zip": "2.0.1", + "progress": "2.0.3", + "proxy-agent": "6.3.1", + "tar-fs": "3.0.4", + "unbzip2-stream": "1.4.3", + "yargs": "17.7.2" + }, + "bin": { + "browsers": "lib/cjs/main-cli.js" + }, + "engines": { + "node": ">=16.3.0" + } + }, + "node_modules/@puppeteer/browsers/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@puppeteer/browsers/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@puppeteer/browsers/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "dev": true + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@types/chai": { + "version": "4.3.14", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.14.tgz", + "integrity": "sha512-Wj71sXE4Q4AkGdG9Tvq1u/fquNz9EdG4LIJMwVVII7ashjD/8cf8fyIfJAjRr6YcsXnSE8cOGQPq1gqeR8z+3w==", + "dev": true + }, + "node_modules/@types/mocha": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", + "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.11.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.10.tgz", + "integrity": "sha512-rZEfe/hJSGYmdfX9tvcPMYeYPW2sNl50nsw4jZmRcaG0HIAb0WYEpsB05GOb53vjqpyE9GUhlDQ4jLSoB5q9kg==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dev": true, + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/b4a": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", + "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/basic-ftp": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.4.tgz", + "integrity": "sha512-8PzkB0arJFV4jJWSGOYR+OEic6aeKMu/osRhBULN6RY0ykby6LKhbmuQ5ublvaas5BOwboah5D87nrHyuh8PPA==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chromium-bidi": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.5.6.tgz", + "integrity": "sha512-ber8smgoAs4EqSUHRb0I8fpx371ZmvsdQav8HRM9oO4fk5Ox16vQiNYXlsZkRj4FfvVL2dCef+zBFQixp+79CA==", + "dev": true, + "dependencies": { + "mitt": "3.0.1", + "urlpattern-polyfill": "10.0.0" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-fetch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", + "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", + "dev": true, + "dependencies": { + "node-fetch": "^2.6.12" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.1.tgz", + "integrity": "sha512-MZd3VlchQkp8rdend6vrx7MmVDJzSNTBvghvKjirLkD+WTChA3KUf0jkE68Q4UyctNqI11zZO9/x2Yx+ub5Cvg==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "dev": true, + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/devtools-protocol": { + "version": "0.0.1232444", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1232444.tgz", + "integrity": "sha512-pM27vqEfxSxRkTMnF+XCmxSEb6duO5R+t8A9DEEJgy4Wz2RVanje2mmj99B6A3zv2r/qGfYlOvYznUhuokizmg==", + "dev": true + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "dev": true + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 ||>=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 ||>=11.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* ||>= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-uri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.2.tgz", + "integrity": "sha512-5KLucCJobh8vBY1K07EFV4+cPZH3mrV9YeAruUseCQKHB58SGjjT2l9/eA9LD082IiuMjSlFJEcdJ27TXvbZNw==", + "dev": true, + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.0", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/husky": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "dev": true, + "bin": { + "husky": "lib/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ip": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz", + "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==", + "dev": true + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "node_modules/mocha": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", + "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==", + "dev": true, + "dependencies": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "8.1.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x ||>=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pac-proxy-agent": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", + "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", + "dev": true, + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", + "pac-resolver": "^7.0.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.0.tgz", + "integrity": "sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==", + "dev": true, + "dependencies": { + "degenerator": "^5.0.0", + "ip": "^1.1.8", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/proxy-agent": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", + "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.1", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/puppeteer": { + "version": "21.10.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-21.10.0.tgz", + "integrity": "sha512-Y1yQjcLE00hHTDAmv3M3A6hhW0Ytjdp6xr6nyjl7FZ7E7hzp/6Rsw80FbaTJzJHFCplBNi082wrgynbmD7RlYw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@puppeteer/browsers": "1.9.1", + "cosmiconfig": "9.0.0", + "puppeteer-core": "21.10.0" + }, + "bin": { + "puppeteer": "lib/esm/puppeteer/node/cli.js" + }, + "engines": { + "node": ">=16.13.2" + } + }, + "node_modules/puppeteer-core": { + "version": "21.10.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-21.10.0.tgz", + "integrity": "sha512-NVaqO3K462qwMuLO4Gurs/Mau1Wss+08QgNYzF0dIqZWMvpskrt/TbxbmHU+7zMTUOvPEq/lR4BLJmjMBgBGfQ==", + "dev": true, + "dependencies": { + "@puppeteer/browsers": "1.9.1", + "chromium-bidi": "0.5.6", + "cross-fetch": "4.0.0", + "debug": "4.3.4", + "devtools-protocol": "0.0.1232444", + "ws": "8.16.0" + }, + "engines": { + "node": ">=16.13.2" + } + }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", + "dev": true + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shellfie": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/shellfie/-/shellfie-1.3.7.tgz", + "integrity": "sha512-4l1Co5D7UNHUKkqwy1ko934I8y8gkwayFLvb481uFo423hNaKHwC5m5JnERAtwayq8xpPcLhJ5IUpT0qECRFxw==", + "dev": true, + "dependencies": { + "puppeteer": "latest", + "xterm": "^4.14.1", + "xterm-addon-fit": "^0.5.0" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/snaptdout": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/snaptdout/-/snaptdout-2.1.0.tgz", + "integrity": "sha512-kqzi5IcBxzDowvSY+l2QFEkKF9jzDPv56M9YPfmD1mYjSzPCyLwdrU6DFDUMU+N36ZQYIWWHeTI9ugPXwXK17g==", + "dev": true + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dev": true, + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", + "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/socks/node_modules/ip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", + "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", + "dev": true + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/streamx": { + "version": "2.15.6", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.6.tgz", + "integrity": "sha512-q+vQL4AAz+FdfT137VF69Cc/APqUbxy+MDOImRrMvchJpigHj9GksgDU2LYbO9rx7RX6osWgxJB2WxhYv4SZAw==", + "dev": true, + "dependencies": { + "fast-fifo": "^1.1.0", + "queue-tick": "^1.0.1" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styl3": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/styl3/-/styl3-1.4.0.tgz", + "integrity": "sha512-RdUDaCy9POYkcAunRcGr+pu1eFcoE4kOQCEpm6Gd0bmTZUXSPzK1dgQOgrNOM9JdAb2/GY2gEUNJN8Hy+mr+8Q==" + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/tar-fs": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", + "integrity": "sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==", + "dev": true, + "dependencies": { + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + } + }, + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dev": true, + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dev": true, + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/urlpattern-polyfill": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", + "dev": true + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xterm": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/xterm/-/xterm-4.19.0.tgz", + "integrity": "sha512-c3Cp4eOVsYY5Q839dR5IejghRPpxciGmLWWaP9g+ppfMeBChMeLa1DCA+pmX/jyDZ+zxFOmlJL/82qVdayVoGQ==", + "deprecated": "This package is now deprecated. Move to @xterm/xterm instead.", + "dev": true + }, + "node_modules/xterm-addon-fit": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xterm-addon-fit/-/xterm-addon-fit-0.5.0.tgz", + "integrity": "sha512-DsS9fqhXHacEmsPxBJZvfj2la30Iz9xk+UKjhQgnYNkrUIN5CYLbw7WEfz117c7+S86S/tpHPfvNxJsF5/G8wQ==", + "deprecated": "This package is now deprecated. Move to @xterm/addon-fit instead.", + "dev": true, + "peerDependencies": { + "xterm": "^4.0.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json index 671c735..735c73f 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ }, "scripts": { "test": "mocha index.test.js", + "test:ts": "mocha -r ts-node/register main.test.ts", "print": "node -e \"const keys = require('./snapshots/index.test'); Object.keys(keys).map(key => console.log(key + '\\n' + keys[key].join('\\n'))) \" " }, "keywords": [ @@ -25,11 +26,15 @@ "author": "Tal Hayut", "license": "MIT", "devDependencies": { + "@types/chai": "4.3.14", + "@types/mocha": "10.0.6", "chai": "4.2.0", "husky": "8.0.3", "mocha": "^10.0.0", "shellfie": "^1.3.1", - "snaptdout": "^2.1.0" + "snaptdout": "^2.1.0", + "ts-node": "10.9.2", + "typescript": "5.4.5" }, "husky": { "hooks": { diff --git a/pp.js b/pp.js new file mode 100644 index 0000000..38a678b --- /dev/null +++ b/pp.js @@ -0,0 +1,30 @@ +const Chartscii = require('./index'); + +// generate random chart data +const data = []; + +for (let i = 1; i <= 10; i++) { + data.push({ value: i + 1, label: `WHAT ${i}` }); + // data.push(i) +} + +// create chart +const chart = new Chartscii(data, { + // label: 'Example Chart', + width: 50, + sort: false, + reverse: false, + // fill: '░', + char: '█', + color: 'red', + label: 'THANKS', + colorLabels: false, + percentage: false, + labels: true, + barWidth: 2, + naked: false, + orientation: 'vertical' +}); + +//print chart +console.log(chart.create()); \ No newline at end of file diff --git a/snapshots/main.test.json b/snapshots/main.test.json new file mode 100644 index 0000000..4c07366 --- /dev/null +++ b/snapshots/main.test.json @@ -0,0 +1,137 @@ +{ + "chart": [ + " \u001b[38;5;219mlabel 0\u001b[0m ╢\u001b[38;5;219m\u001b[0m", + " \u001b[38;5;219mlabel 1\u001b[0m ╢\u001b[38;5;219m█████\u001b[0m", + " \u001b[38;5;219mlabel 2\u001b[0m ╢\u001b[38;5;219m███████████\u001b[0m", + " \u001b[38;5;219mlabel 3\u001b[0m ╢\u001b[38;5;219m████████████████\u001b[0m", + " \u001b[38;5;219mlabel 4\u001b[0m ╢\u001b[38;5;219m█████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 5\u001b[0m ╢\u001b[38;5;219m██████████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 6\u001b[0m ╢\u001b[38;5;219m████████████████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 7\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 8\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 9\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 10\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 11\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 12\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 13\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 14\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 15\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 16\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 17\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 18\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 19\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" + ], + "percentage": [ + " \u001b[38;5;219mlabel 0 (0.5%)\u001b[0m ╢\u001b[38;5;219m█████\u001b[0m", + " \u001b[38;5;219mlabel 1 (1.0%)\u001b[0m ╢\u001b[38;5;219m██████████\u001b[0m", + " \u001b[38;5;219mlabel 2 (1.4%)\u001b[0m ╢\u001b[38;5;219m███████████████\u001b[0m", + " \u001b[38;5;219mlabel 3 (1.9%)\u001b[0m ╢\u001b[38;5;219m████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 4 (2.4%)\u001b[0m ╢\u001b[38;5;219m█████████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 5 (2.9%)\u001b[0m ╢\u001b[38;5;219m██████████████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 6 (3.3%)\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 7 (3.8%)\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 8 (4.3%)\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████████████\u001b[0m", + " \u001b[38;5;219mlabel 9 (4.8%)\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 10 (5.2%)\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 11 (5.7%)\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 12 (6.2%)\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 13 (6.7%)\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 14 (7.1%)\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 15 (7.6%)\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 16 (8.1%)\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 17 (8.6%)\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 18 (9.0%)\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 19 (9.5%)\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" + ], + "labeless chart": [ + " ║█████", + " ║██████████", + " ║███████████████", + " ║████████████████████", + " ║█████████████████████████", + " ║██████████████████████████████", + " ║███████████████████████████████████", + " ║████████████████████████████████████████", + " ║█████████████████████████████████████████████", + " ║██████████████████████████████████████████████████", + " ║███████████████████████████████████████████████████████", + " ║████████████████████████████████████████████████████████████", + " ║█████████████████████████████████████████████████████████████████", + " ║██████████████████████████████████████████████████████████████████████", + " ║███████████████████████████████████████████████████████████████████████████", + " ║████████████████████████████████████████████████████████████████████████████████", + " ║█████████████████████████████████████████████████████████████████████████████████████", + " ║██████████████████████████████████████████████████████████████████████████████████████████", + " ║███████████████████████████████████████████████████████████████████████████████████████████████", + " ║████████████████████████████████████████████████████████████████████████████████████████████████████", + " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" + ], + "labeless color chart": [ + " ║\u001b[38;5;160m█████████████\u001b[0m", + " ║\u001b[32m█████████████████████████\u001b[0m", + " ║\u001b[38;5;227m██████████████████████████████████████\u001b[0m", + " ║\u001b[34m██████████████████████████████████████████████████\u001b[0m", + " ║\u001b[35m███████████████████████████████████████████████████████████████\u001b[0m", + " ║\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", + " ║\u001b[96m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + " ║\u001b[38;5;215m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" + ], + "pastel theme": [ + " \u001b[31mred\u001b[0m ╢\u001b[31m█████████████\u001b[0m", + " \u001b[38;5;49mgreen\u001b[0m ╢\u001b[38;5;49m█████████████████████████\u001b[0m", + "\u001b[38;5;228myellow\u001b[0m ╢\u001b[38;5;228m██████████████████████████████████████\u001b[0m", + " \u001b[38;5;39mblue\u001b[0m ╢\u001b[38;5;39m██████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;147mpurple\u001b[0m ╢\u001b[38;5;147m███████████████████████████████████████████████████████████████\u001b[0m", + " \u001b[38;5;219mpink\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", + " \u001b[38;5;159mcyan\u001b[0m ╢\u001b[38;5;159m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;209morange\u001b[0m ╢\u001b[38;5;209m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" + ], + "lush theme": [ + " \u001b[38;5;196mred\u001b[0m ╢\u001b[38;5;196m█████████████\u001b[0m", + " \u001b[38;5;154mgreen\u001b[0m ╢\u001b[38;5;154m█████████████████████████\u001b[0m", + "\u001b[38;5;226myellow\u001b[0m ╢\u001b[38;5;226m██████████████████████████████████████\u001b[0m", + " \u001b[38;5;57mblue\u001b[0m ╢\u001b[38;5;57m██████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;128mpurple\u001b[0m ╢\u001b[38;5;128m███████████████████████████████████████████████████████████████\u001b[0m", + " \u001b[38;5;198mpink\u001b[0m ╢\u001b[38;5;198m███████████████████████████████████████████████████████████████████████████\u001b[0m", + " \u001b[38;5;87mcyan\u001b[0m ╢\u001b[38;5;87m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;202morange\u001b[0m ╢\u001b[38;5;202m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" + ], + "standard theme": [ + " \u001b[38;5;9mred\u001b[0m ╢\u001b[38;5;9m█████████████\u001b[0m", + " \u001b[38;5;10mgreen\u001b[0m ╢\u001b[38;5;10m█████████████████████████\u001b[0m", + "\u001b[38;5;11myellow\u001b[0m ╢\u001b[38;5;11m██████████████████████████████████████\u001b[0m", + " \u001b[38;5;27mblue\u001b[0m ╢\u001b[38;5;27m██████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;105mpurple\u001b[0m ╢\u001b[38;5;105m███████████████████████████████████████████████████████████████\u001b[0m", + " \u001b[38;5;200mpink\u001b[0m ╢\u001b[38;5;200m███████████████████████████████████████████████████████████████████████████\u001b[0m", + " \u001b[38;5;123mcyan\u001b[0m ╢\u001b[38;5;123m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;214morange\u001b[0m ╢\u001b[38;5;214m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" + ], + "beach theme": [ + " \u001b[38;2;254;74;73mred\u001b[0m ╢\u001b[38;2;254;74;73m█████████████\u001b[0m", + " \u001b[38;2;42;183;202mgreen\u001b[0m ╢\u001b[38;2;42;183;202m█████████████████████████\u001b[0m", + "\u001b[38;2;254;215;102myellow\u001b[0m ╢\u001b[38;2;254;215;102m██████████████████████████████████████\u001b[0m", + " \u001b[38;2;146;196;238mblue\u001b[0m ╢\u001b[38;2;146;196;238m██████████████████████████████████████████████████\u001b[0m", + "\u001b[38;2;130;119;249mpurple\u001b[0m ╢\u001b[38;2;130;119;249m███████████████████████████████████████████████████████████████\u001b[0m", + " \u001b[38;2;222;82;133mpink\u001b[0m ╢\u001b[38;2;222;82;133m███████████████████████████████████████████████████████████████████████████\u001b[0m", + " \u001b[38;2;0;255;255mcyan\u001b[0m ╢\u001b[38;2;0;255;255m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;2;247;126;2morange\u001b[0m ╢\u001b[38;2;247;126;2m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" + ], + "default theme": [ + " \u001b[38;5;160mred\u001b[0m ╢\u001b[38;5;160m█████████████\u001b[0m", + " \u001b[32mgreen\u001b[0m ╢\u001b[32m█████████████████████████\u001b[0m", + "\u001b[38;5;227myellow\u001b[0m ╢\u001b[38;5;227m██████████████████████████████████████\u001b[0m", + " \u001b[34mblue\u001b[0m ╢\u001b[34m██████████████████████████████████████████████████\u001b[0m", + "\u001b[35mpurple\u001b[0m ╢\u001b[35m███████████████████████████████████████████████████████████████\u001b[0m", + " \u001b[38;5;219mpink\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", + " \u001b[96mcyan\u001b[0m ╢\u001b[96m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;215morange\u001b[0m ╢\u001b[38;5;215m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" + ] +} \ No newline at end of file diff --git a/ts/main.test.ts b/ts/main.test.ts new file mode 100644 index 0000000..bbdb729 --- /dev/null +++ b/ts/main.test.ts @@ -0,0 +1,140 @@ +import chai from 'chai'; +const expect = chai.expect; +import Chartscii from './main'; +import snap from 'snaptdout'; +const colors = [ + 'red', + 'green', + 'yellow', + 'blue', + 'purple', + 'pink', + 'cyan', + 'orange', +]; + +function generateChartData() { + const data = []; + for (let i = 0; i < colors.length; i++) { + const color = colors[i]; + data.push({ value: i + 1, label: color, color }); + } + return data; +} + +describe('chartscii tests', () => { + let data, chart: any; + + beforeEach(() => { + data = [...Array(10).keys()]; + chart = new Chartscii(data); + }); + + it('should initialize chart array with all values', () => { + const result = chart.get(); + expect(result.length).to.equal(10); + }); + + it('should support 0 values', () => { + const result = chart.get(); + expect(result[0]).to.include({ value: '0' }); + }); + + it('should support { value }', () => { + const data = [...Array(10).keys()].map((key) => { + return { value: key }; + }); + chart = new Chartscii(data); + const result = chart.get()[0]; + expect(result.value).to.equal('0'); + }); + + it('should support { value, label }', () => { + let counter = 0; + const data = [...Array(10).keys()].map((key) => { + return { value: key, label: `label ${counter++}` }; + }); + chart = new Chartscii(data); + const result = chart.get()[0]; + expect(result.label).to.equal('label 0'); + }); + + it('should support percentage', () => { + let counter = 0; + const data = [...Array(10).keys()].map((key) => { + return { value: key, label: `label ${counter++}` }; + }); + chart = new Chartscii(data, { percentage: true }); + const result = chart.get()[0]; + expect(result.label).to.include('%'); + }); +}); + +describe('examples', () => { + it('should match example', async () => { + const data = []; + for (let i = 0; i < 20; i++) { + data.push({ value: i, label: `label ${i}` }); + } + const chart = new Chartscii(data, { color: 'pink', colorLabels: true }); + await snap(chart.create(), 'chart'); + }); + it('should support percentage', async () => { + const data = []; + for (let i = 0; i < 20; i++) { + data.push({ value: i + 1, label: `label ${i}` }); + } + const chart = new Chartscii(data, { + color: 'pink', + colorLabels: true, + percentage: true, + }); + await snap(chart.create(), 'percentage'); + }); + + it('should support labeless chart', async () => { + const data = []; + for (let i = 0; i < 20; i++) { + data.push(i + 1); + } + const chart = new Chartscii(data, { labels: false }); + await snap(chart.create(), 'labeless chart'); + }); + + it('should support labeless colorful chart', async () => { + const data = []; + for (let i = 0; i < colors.length; i++) { + const color = colors[i]; + data.push({ value: i + 1, color }); + } + const chart = new Chartscii(data, { labels: false }); + await snap(chart.create(), 'labeless color chart'); + }); + + it('should support pastel theme', async () => { + const data = generateChartData(); + const chart = new Chartscii(data, { theme: 'pastel', colorLabels: true }); + await snap(chart.create(), 'pastel theme'); + }); + it('should support lush theme', async () => { + const data = generateChartData(); + const chart = new Chartscii(data, { theme: 'lush', colorLabels: true }); + await snap(chart.create(), 'lush theme'); + }); + it('should support standard theme', async () => { + const data = generateChartData(); + const chart = new Chartscii(data, { theme: 'standard', colorLabels: true }); + await snap(chart.create(), 'standard theme'); + }); + it('should support beach theme', async () => { + const data = generateChartData(); + const chart = new Chartscii(data, { theme: 'beach', colorLabels: true }); + await snap(chart.create(), 'beach theme'); + }); + it('should support default theme', async () => { + const data = generateChartData(); + const chart = new Chartscii(data, { colorLabels: true }); + await snap(chart.create(), 'default theme'); + }); + +}); diff --git a/ts/main.ts b/ts/main.ts new file mode 100644 index 0000000..dca1df3 --- /dev/null +++ b/ts/main.ts @@ -0,0 +1,260 @@ +import style from 'styl3'; +import defaultOptions from '../config/config'; +import { ChartData, ChartOptions, ChartPoint, Measures, Point } from './types'; +import { getPointValue } from '../utils'; + +class Chartscii { + private chart: ChartPoint[]; + private measures: Measures; + private options: ChartOptions; + private colors: Record; + private width: number; + private data: ChartData; + + constructor(data: ChartData, options?: ChartOptions) { + this.chart = []; + this.measures = { numeric: 0, count: 0, label: 0, space: 1 } + this.options = this.setOptions(options); + this.colors = style({ theme: this.options.theme }); + this.width = this.options.width; + this.data = this.sortData(data, this.options.reverse); + this.createGraphAxis(); + } + + setOptions(options: ChartOptions = {}) { + const newOptions = { ...defaultOptions, ...options }; + return newOptions; + } + + sortData(data: ChartData, reverse?: boolean) { + if (this.options.sort) { + data = this.sortSmallToLarge(data); + } + if (reverse) { + data = data.reverse(); + } + return data; + } + + getTotal(data: ChartData): number { + return data.reduce((a, p) => a += getPointValue(p), 0); + } + + getPercentageData(value: number, label?: string) { + const total = this.getTotal(this.data); + const avg = value / total; + const percentage = `${(avg * 100).toFixed(1)}%`; + return `${label || value} (${percentage})`; + } + + colorLabel(label: string, color: string) { + return label.toString().replace(label, this.colorify(label, color)); + } + + updateMaxLabelLength(label: string) { + return label.length>= this.measures.label + ? label.length + : this.measures.label; + } + + updateMaxNumeric(value: number) { + return value>= this.measures.numeric ? value : this.measures.numeric; + } + + colorify(txt: string, color: string) { + if (color) { + if (color.includes('#')) { + return this.colors.hex(color)`${txt}`; + } else if (color.match(/[0-9]/)) { + return this.colors.ansi(color)`${txt}`; + } else if (Array.isArray(color)) { + return this.colors.rgb(...color)`${txt}`; + } else { + return this.colors[color]`${txt}`; + } + } + } + + createGraphAxis() { + this.measures.space = this.measures.label || 1; + + const lines = this.data.map((point) => this.line(point)); + + for (const point of lines) { + const value = getPointValue(point); + const color = point.color || this.options.color; + + if (!point.label) { + const key = this.formatLabelessLine(point, value); + this.chart.push({ key, value, color }); + } else { + const key = this.formatLabelLine(point); + this.chart.push({ key, ...point, value }); + } + } + + return this.chart; + } + + formatLabelessLine(point: any, value: any) { + const space = this.measures.label - point.labelColorLess; + if (this.options.labels !== false) { + return this.formatLine(space, value); + } + + return this.options.naked + ? `${' '.repeat(space + value.length)}` + : `${' '.repeat(space + value.length)} ${this.options.structure.noLabelChar + }`; + } + + formatLabelLine(point: any) { + const space = this.measures.label - (point.labelColorLess || point.label.length); + return this.formatLine(space, point.label); + } + + formatLine(space: any, value: any) { + return this.options.naked + ? `${' '.repeat(space)}${value} ` + : `${' '.repeat(space)}${value} ${this.options.structure.y}`; + } + + line(point: Point | number) { + const label = point.label; + const rawValue = getPointValue(point); + const value = rawValue === 0 ? rawValue.toString() : rawValue + + this.measures.numeric = this.updateMaxNumeric(rawValue); + + if (label) { + return this.makeLabelPoint(point) + } + + return this.makeValuePoint({ ...point, value }); + + } + + makeLabelPoint(point: Point & {labelColorLess: number}) { + const value = typeof point === 'object' ? point.value : point; + const color = point.color || this.options.color; + const label = point.label; + + this.measures.label = this.updateMaxLabelLength(point.label); + point.labelColorLess = point.label.length; + + if (this.options.percentage) { + point.label = this.getPercentageData(value, label); + point.labelColorLess = point.label.length; + this.measures.label = this.updateMaxLabelLength(point.label); + } + + if (this.options.colorLabels) { + point.label = this.colorLabel(point.label, color); + } + + return point; + } + + makeValuePoint(point: any) { + const color = point.color || this.options.color; + const value = getPointValue(point); + + let labelColorLess = value.toString().length; + this.measures.label = this.updateMaxLabelLength(value.toString()); + + if (this.options.percentage) { + point.label = this.getPercentageData(value); + this.measures.label = this.updateMaxLabelLength(point.label); + labelColorLess = point.label.length; + } + + if (this.options.colorLabels) { + const printValue = point.label || value; + point.label = this.colorLabel(printValue, color); + } + + return { value, label: point.label, labelColorLess, color }; + } + + sortSmallToLarge(arr: any) { + const sorted = arr.sort((a: any, b: any) => { + if (a.label && this.options.sort) { + return a.label.toLowerCase().localeCompare(b.label.toLowerCase()); + } + if (a.value) { + return a.value - b.value; + } + return a - b; + }); + + return sorted; + } + + makeSpace() { + if (this.measures.space === 2) { + return ' '.repeat(this.measures.space + 1); + } + if (this.measures.space % 2 === 0) { + return ' '.repeat(this.measures.space); + } else if (this.measures.space % 3 === 0) { + return this.measures.space === 3 ? ' ' : ' '.repeat(this.measures.space - 7); + } else if (this.measures.space < 2) { + return ' '.repeat(this.measures.space + 1); + } else { + return ' '.repeat(this.measures.space - 3); + } + } + + makeChartLabel() { + if (this.options.label) { + const space = ' '.repeat(this.measures.space + 1); + return this.options.color + ? `${this.colorify(this.options.label, this.options.color)}${this.colors.colors.reset}${space}` + : `${this.options.label}${space}`; + } + + return ''; + } + + makeChartBottom() { + const base = this.options.labels + ? ' '.repeat(this.measures.label + 1) + this.options.structure.leftCorner + : ' '.repeat(this.measures.label> 1 ? this.measures.label - 1 : this.measures.label) + this.options.structure.leftCorner; + + return base + this.options.structure.x.repeat((this.width / 2)) + } + + create() { + const asciiChart = []; + + for (const point of this.chart) { + const color = point.color || this.options.color; + const scaledValue = this.getScaledValue(point.value); + const fill = this.options.fill ? this.options.fill.repeat(this.width - scaledValue) : ''; + const line = color + ? `${point.key}${this.colorify(`${this.options.char.repeat(scaledValue)}${fill}`, color)}` + : `${point.key}${this.options.char.repeat(scaledValue)}${fill}` + + asciiChart.push(line); + } + + if (this.options.label) { + asciiChart.push(this.makeChartLabel()); + } + + asciiChart.push(this.makeChartBottom()) + return asciiChart.join('\n'); + } + + + + getScaledValue(value: any) { + return Math.round((value / this.measures.numeric) * this.width); + } + + get() { + return this.chart; + } +} + +export default Chartscii; diff --git a/ts/tsconfig.json b/ts/tsconfig.json new file mode 100644 index 0000000..94b20bf --- /dev/null +++ b/ts/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "es2020", // Compile to ECMAScript 2020. Supports modern JS features. + "module": "commonjs", // Use CommonJS module system, suitable for Node.js. + "lib": ["es2020", "dom"], // Include typings for ES2020 and DOM (optional, remove if not manipulating DOM). + "outDir": "./dist", // Output directory for compiled files. + "rootDir": ".", // Root directory of source files. + "strict": false, // Enable all strict type-checking options. + "esModuleInterop": true, // Enables emit interoperability between CommonJS and ES Modules. + "moduleResolution": "node", // Resolve modules using Node.js's module resolution strategy. + "allowJs": true, // Allow JavaScript files to be compiled. + "noImplicitAny": true, // Raise error on expressions and declarations with an implied 'any' type. + "noImplicitReturns": true, // Report error when not all code paths in function return a value. + "noUnusedLocals": true, // Report errors on unused local variables. + "noUnusedParameters": true, // Report errors on unused parameters. + "removeComments": true, // Do not emit comments to output. + "sourceMap": true, // Generates corresponding '.map' file. + "types": ["@types/mocha", "@types/node"] + }, +} diff --git a/ts/types.ts b/ts/types.ts new file mode 100644 index 0000000..9d41e36 --- /dev/null +++ b/ts/types.ts @@ -0,0 +1,42 @@ +export type ChartPoint = { + key: string; + value: number | string; + color?: string; + label?: string; +} + +export type Measures = { + numeric: number; + count: number; + label: number; + space: number; +} + +export type ChartOptions = { + sort?: boolean; + percentage?: boolean; + colorLabels?: boolean; + reverse?: boolean; + naked?: boolean; + labels?: boolean; + color?: string; + label?: string; + char?: string; + fill?: string; + width?: number; + theme?: string; + structure?: { + y: string; + x: string; + leftCorner: string; + noLabelChar: string; + }, +} + +export type Point = { + value: number; + color?: string; + label?: string; +} + +export type ChartData = Point[] | number[]; \ No newline at end of file diff --git a/ts/utils.ts b/ts/utils.ts new file mode 100644 index 0000000..85329f5 --- /dev/null +++ b/ts/utils.ts @@ -0,0 +1,9 @@ +import { Point } from './types'; + +export function getPointValue(point: Point | number): number { + return typeof point === "number" ? point : point.value; +} + +export function getPointLabel(point: Point | number): string { + return typeof point === "number" ? point.toString() : point.label; +} \ No newline at end of file diff --git a/utils.js b/utils.js index a069109..229e9b2 100644 --- a/utils.js +++ b/utils.js @@ -2,4 +2,12 @@ function getPointValue(point) { return typeof point === "object" ? point.value : point; } -module.exports = { getPointValue } \ No newline at end of file +function getPointLabel(point) { + return typeof point === "number" ? point.toString() : point.label; +} + +function padLine(padding, line) { + return ' '.repeat(padding) + line + ' '.repeat(padding); +} + +module.exports = { getPointValue, getPointLabel, padLine } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 6cddd56..9ea7876 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4,7 +4,7 @@ "@babel/code-frame@^7.0.0": version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz" integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== dependencies: "@babel/highlight" "^7.23.4" @@ -12,21 +12,46 @@ "@babel/helper-validator-identifier@^7.22.20": version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz" integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== "@babel/highlight@^7.23.4": version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz" integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== dependencies: "@babel/helper-validator-identifier" "^7.22.20" chalk "^2.4.2" js-tokens "^4.0.0" +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.2" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.15" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@puppeteer/browsers@1.9.1": version "1.9.1" - resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-1.9.1.tgz#384ee8b09786f0e8f62b1925e4c492424cb549ee" + resolved "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.9.1.tgz" integrity sha512-PuvK6xZzGhKPvlx3fpfdM2kYY3P/hB1URtK8wA7XUJ6prn6pp22zvJHu48th0SGcHL9SutbPHrFuQgfXTFobWA== dependencies: debug "4.3.4" @@ -39,131 +64,176 @@ "@tootallnate/quickjs-emscripten@^0.23.0": version "0.23.0" - resolved "https://registry.yarnpkg.com/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz#db4ecfd499a9765ab24002c3b696d02e6d32a12c" + resolved "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz" integrity sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA== +"@tsconfig/node10@^1.0.7": + version "1.0.11" + resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz" + integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@types/chai@4.3.14": + version "4.3.14" + resolved "https://registry.npmjs.org/@types/chai/-/chai-4.3.14.tgz" + integrity sha512-Wj71sXE4Q4AkGdG9Tvq1u/fquNz9EdG4LIJMwVVII7ashjD/8cf8fyIfJAjRr6YcsXnSE8cOGQPq1gqeR8z+3w== + +"@types/mocha@10.0.6": + version "10.0.6" + resolved "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz" + integrity sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg== + "@types/node@*": version "20.11.10" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.10.tgz#6c3de8974d65c362f82ee29db6b5adf4205462f9" + resolved "https://registry.npmjs.org/@types/node/-/node-20.11.10.tgz" integrity sha512-rZEfe/hJSGYmdfX9tvcPMYeYPW2sNl50nsw4jZmRcaG0HIAb0WYEpsB05GOb53vjqpyE9GUhlDQ4jLSoB5q9kg== dependencies: undici-types "~5.26.4" "@types/yauzl@^2.9.1": version "2.10.3" - resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.3.tgz#e9b2808b4f109504a03cda958259876f61017999" + resolved "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz" integrity sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q== dependencies: "@types/node" "*" +acorn-walk@^8.1.1: + version "8.3.2" + resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz" + integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== + +acorn@^8.4.1: + version "8.11.3" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz" + integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== + agent-base@^7.0.2, agent-base@^7.1.0: version "7.1.0" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.0.tgz#536802b76bc0b34aa50195eb2442276d613e3434" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz" integrity sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg== dependencies: debug "^4.3.4" ansi-colors@4.1.1: version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== ansi-regex@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" anymatch@~3.1.2: version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + argparse@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== assertion-error@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== ast-types@^0.13.4: version "0.13.4" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.4.tgz#ee0d77b343263965ecc3fb62da16e7222b2b6782" + resolved "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz" integrity sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w== dependencies: tslib "^2.0.1" b4a@^1.6.4: version "1.6.4" - resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.6.4.tgz#ef1c1422cae5ce6535ec191baeed7567443f36c9" + resolved "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz" integrity sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw== balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== base64-js@^1.3.1: version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== basic-ftp@^5.0.2: version "5.0.4" - resolved "https://registry.yarnpkg.com/basic-ftp/-/basic-ftp-5.0.4.tgz#28aeab7bfbbde5f5d0159cd8bb3b8e633bbb091d" + resolved "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.4.tgz" integrity sha512-8PzkB0arJFV4jJWSGOYR+OEic6aeKMu/osRhBULN6RY0ykby6LKhbmuQ5ublvaas5BOwboah5D87nrHyuh8PPA== binary-extensions@^2.0.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== brace-expansion@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz" integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== dependencies: balanced-match "^1.0.0" braces@~3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== dependencies: fill-range "^7.0.1" browser-stdout@1.3.1: version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== buffer-crc32@~0.2.3: version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + resolved "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz" integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== buffer@^5.2.1: version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== dependencies: base64-js "^1.3.1" @@ -171,17 +241,17 @@ buffer@^5.2.1: callsites@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== camelcase@^6.0.0: version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== chai@4.2.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" + resolved "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz" integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw== dependencies: assertion-error "^1.1.0" @@ -193,7 +263,7 @@ chai@4.2.0: chalk@^2.4.2: version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" @@ -202,7 +272,7 @@ chalk@^2.4.2: chalk@^4.1.0: version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== dependencies: ansi-styles "^4.1.0" @@ -210,14 +280,14 @@ chalk@^4.1.0: check-error@^1.0.2: version "1.0.3" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" + resolved "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz" integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== dependencies: get-func-name "^2.0.2" chokidar@3.5.3: version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== dependencies: anymatch "~3.1.2" @@ -232,7 +302,7 @@ chokidar@3.5.3: chromium-bidi@0.5.6: version "0.5.6" - resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-0.5.6.tgz#a19e0aacda098878b49428939a39c477db0b4c45" + resolved "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.5.6.tgz" integrity sha512-ber8smgoAs4EqSUHRb0I8fpx371ZmvsdQav8HRM9oO4fk5Ox16vQiNYXlsZkRj4FfvVL2dCef+zBFQixp+79CA== dependencies: mitt "3.0.1" @@ -240,7 +310,7 @@ chromium-bidi@0.5.6: cliui@^7.0.2: version "7.0.4" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz" integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== dependencies: string-width "^4.2.0" @@ -249,7 +319,7 @@ cliui@^7.0.2: cliui@^8.0.1: version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz" integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== dependencies: string-width "^4.2.0" @@ -258,31 +328,31 @@ cliui@^8.0.1: color-convert@^1.9.0: version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-convert@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== dependencies: color-name "~1.1.4" -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - color-name@~1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + cosmiconfig@9.0.0: version "9.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-9.0.0.tgz#34c3fc58287b915f3ae905ab6dc3de258b55ad9d" + resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz" integrity sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg== dependencies: env-paths "^2.2.1" @@ -290,98 +360,108 @@ cosmiconfig@9.0.0: js-yaml "^4.1.0" parse-json "^5.2.0" +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + cross-fetch@4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.0.0.tgz#f037aef1580bb3a1a35164ea2a848ba81b445983" + resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz" integrity sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g== dependencies: node-fetch "^2.6.12" data-uri-to-buffer@^6.0.0: version "6.0.1" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-6.0.1.tgz#540bd4c8753a25ee129035aebdedf63b078703c7" + resolved "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.1.tgz" integrity sha512-MZd3VlchQkp8rdend6vrx7MmVDJzSNTBvghvKjirLkD+WTChA3KUf0jkE68Q4UyctNqI11zZO9/x2Yx+ub5Cvg== -debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.4: +debug@^4.1.1, debug@^4.3.4, debug@4, debug@4.3.4: version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" decamelize@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== deep-eql@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz" integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== dependencies: type-detect "^4.0.0" degenerator@^5.0.0: version "5.0.1" - resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-5.0.1.tgz#9403bf297c6dad9a1ece409b37db27954f91f2f5" + resolved "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz" integrity sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ== dependencies: ast-types "^0.13.4" escodegen "^2.1.0" esprima "^4.0.1" -devtools-protocol@0.0.1232444: +devtools-protocol@*, devtools-protocol@0.0.1232444: version "0.0.1232444" - resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1232444.tgz#406345a90a871ba852c530d73482275234936eed" + resolved "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1232444.tgz" integrity sha512-pM27vqEfxSxRkTMnF+XCmxSEb6duO5R+t8A9DEEJgy4Wz2RVanje2mmj99B6A3zv2r/qGfYlOvYznUhuokizmg== +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + diff@5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + resolved "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz" integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== emoji-regex@^8.0.0: version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== end-of-stream@^1.1.0: version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: once "^1.4.0" env-paths@^2.2.1: version "2.2.1" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + resolved "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz" integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== error-ex@^1.3.1: version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" escalade@^3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-string-regexp@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + escodegen@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17" + resolved "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz" integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== dependencies: esprima "^4.0.1" @@ -392,22 +472,22 @@ escodegen@^2.1.0: esprima@^4.0.1: version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== estraverse@^5.2.0: version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== esutils@^2.0.2: version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== extract-zip@2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" + resolved "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz" integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== dependencies: debug "^4.1.1" @@ -418,26 +498,26 @@ extract-zip@2.0.1: fast-fifo@^1.1.0, fast-fifo@^1.2.0: version "1.3.2" - resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" + resolved "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz" integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== fd-slicer@~1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + resolved "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz" integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g== dependencies: pend "~1.2.0" fill-range@^7.0.1: version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== dependencies: to-regex-range "^5.0.1" find-up@5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== dependencies: locate-path "^6.0.0" @@ -445,12 +525,12 @@ find-up@5.0.0: flat@^5.0.2: version "5.0.2" - resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== fs-extra@^8.1.0: version "8.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz" integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== dependencies: graceful-fs "^4.2.0" @@ -459,34 +539,34 @@ fs-extra@^8.1.0: fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@~2.3.2: version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== get-caller-file@^2.0.5: version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== get-func-name@^2.0.0, get-func-name@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" + resolved "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz" integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== get-stream@^5.1.0: version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz" integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== dependencies: pump "^3.0.0" get-uri@^6.0.1: version "6.0.2" - resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-6.0.2.tgz#e019521646f4a8ff6d291fbaea2c46da204bb75b" + resolved "https://registry.npmjs.org/get-uri/-/get-uri-6.0.2.tgz" integrity sha512-5KLucCJobh8vBY1K07EFV4+cPZH3mrV9YeAruUseCQKHB58SGjjT2l9/eA9LD082IiuMjSlFJEcdJ27TXvbZNw== dependencies: basic-ftp "^5.0.2" @@ -496,14 +576,14 @@ get-uri@^6.0.1: glob-parent@~5.1.2: version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" glob@8.1.0: version "8.1.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + resolved "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz" integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== dependencies: fs.realpath "^1.0.0" @@ -514,27 +594,27 @@ glob@8.1.0: graceful-fs@^4.1.6, graceful-fs@^4.2.0: version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== he@1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== http-proxy-agent@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz#e9096c5afd071a3fce56e6252bb321583c124673" + resolved "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz" integrity sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ== dependencies: agent-base "^7.1.0" @@ -542,7 +622,7 @@ http-proxy-agent@^7.0.0: https-proxy-agent@^7.0.2: version "7.0.2" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz#e2645b846b90e96c6e6f347fb5b2e41f1590b09b" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz" integrity sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA== dependencies: agent-base "^7.0.2" @@ -550,17 +630,17 @@ https-proxy-agent@^7.0.2: husky@8.0.3: version "8.0.3" - resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" + resolved "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz" integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== ieee754@^1.1.13: version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== import-fresh@^3.3.0: version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== dependencies: parent-module "^1.0.0" @@ -568,7 +648,7 @@ import-fresh@^3.3.0: inflight@^1.0.4: version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" @@ -576,102 +656,102 @@ inflight@^1.0.4: inherits@2: version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== ip@^1.1.8: version "1.1.9" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.9.tgz#8dfbcc99a754d07f425310b86a99546b1151e396" + resolved "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz" integrity sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ== ip@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105" + resolved "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz" integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ== is-arrayish@^0.2.1: version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== is-binary-path@~2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== dependencies: binary-extensions "^2.0.0" is-extglob@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-fullwidth-code-point@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" is-number@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== is-plain-obj@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== is-unicode-supported@^0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@4.1.0, js-yaml@^4.1.0: +js-yaml@^4.1.0, js-yaml@4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: argparse "^2.0.1" json-parse-even-better-errors@^2.3.0: version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== jsonfile@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz" integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== optionalDependencies: graceful-fs "^4.1.6" lines-and-columns@^1.1.6: version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== locate-path@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== dependencies: p-locate "^5.0.0" log-symbols@4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz" integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== dependencies: chalk "^4.1.0" @@ -679,36 +759,34 @@ log-symbols@4.1.0: lru-cache@^7.14.1: version "7.18.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz" integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== -minimatch@5.0.1: +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +minimatch@^5.0.1, minimatch@5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz" integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== dependencies: brace-expansion "^2.0.1" -minimatch@^5.0.1: - version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== - dependencies: - brace-expansion "^2.0.1" - mitt@3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1" + resolved "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz" integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== mkdirp-classic@^0.5.2: version "0.5.3" - resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + resolved "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== mocha@^10.0.0: version "10.4.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.4.0.tgz#ed03db96ee9cfc6d20c56f8e2af07b961dbae261" + resolved "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz" integrity sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA== dependencies: ansi-colors "4.1.1" @@ -734,55 +812,55 @@ mocha@^10.0.0: ms@2.1.2: version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== ms@2.1.3: version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== netmask@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/netmask/-/netmask-2.0.2.tgz#8b01a07644065d536383835823bc52004ebac5e7" + resolved "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz" integrity sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg== node-fetch@^2.6.12: version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: whatwg-url "^5.0.0" normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" p-limit@^3.0.2: version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: yocto-queue "^0.1.0" p-locate@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== dependencies: p-limit "^3.0.2" pac-proxy-agent@^7.0.1: version "7.0.1" - resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz#6b9ddc002ec3ff0ba5fdf4a8a21d363bcc612d75" + resolved "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz" integrity sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A== dependencies: "@tootallnate/quickjs-emscripten" "^0.23.0" @@ -796,7 +874,7 @@ pac-proxy-agent@^7.0.1: pac-resolver@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-7.0.0.tgz#79376f1ca26baf245b96b34c339d79bff25e900c" + resolved "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.0.tgz" integrity sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg== dependencies: degenerator "^5.0.0" @@ -805,14 +883,14 @@ pac-resolver@^7.0.0: parent-module@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== dependencies: callsites "^3.0.0" parse-json@^5.2.0: version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== dependencies: "@babel/code-frame" "^7.0.0" @@ -822,32 +900,32 @@ parse-json@^5.2.0: path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== pathval@^1.1.0: version "1.1.1" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + resolved "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== pend@~1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + resolved "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz" integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== picomatch@^2.0.4, picomatch@^2.2.1: version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== progress@2.0.3: version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + resolved "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== proxy-agent@6.3.1: version "6.3.1" - resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-6.3.1.tgz#40e7b230552cf44fd23ffaf7c59024b692612687" + resolved "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz" integrity sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ== dependencies: agent-base "^7.0.2" @@ -861,12 +939,12 @@ proxy-agent@6.3.1: proxy-from-env@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== pump@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + resolved "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz" integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== dependencies: end-of-stream "^1.1.0" @@ -874,7 +952,7 @@ pump@^3.0.0: puppeteer-core@21.10.0: version "21.10.0" - resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-21.10.0.tgz#d1b61c44e258e51e0fa74f1110c540be096a3e28" + resolved "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-21.10.0.tgz" integrity sha512-NVaqO3K462qwMuLO4Gurs/Mau1Wss+08QgNYzF0dIqZWMvpskrt/TbxbmHU+7zMTUOvPEq/lR4BLJmjMBgBGfQ== dependencies: "@puppeteer/browsers" "1.9.1" @@ -886,7 +964,7 @@ puppeteer-core@21.10.0: puppeteer@latest: version "21.10.0" - resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-21.10.0.tgz#0cfa8f57ca8d4d53a5f843715a270d36acd36b86" + resolved "https://registry.npmjs.org/puppeteer/-/puppeteer-21.10.0.tgz" integrity sha512-Y1yQjcLE00hHTDAmv3M3A6hhW0Ytjdp6xr6nyjl7FZ7E7hzp/6Rsw80FbaTJzJHFCplBNi082wrgynbmD7RlYw== dependencies: "@puppeteer/browsers" "1.9.1" @@ -895,48 +973,48 @@ puppeteer@latest: queue-tick@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/queue-tick/-/queue-tick-1.0.1.tgz#f6f07ac82c1fd60f82e098b417a80e52f1f4c142" + resolved "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz" integrity sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag== randombytes@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" readdirp@~3.6.0: version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== dependencies: picomatch "^2.2.1" require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== resolve-from@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== safe-buffer@^5.1.0: version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== serialize-javascript@6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz" integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== dependencies: randombytes "^2.1.0" shellfie@^1.3.1: version "1.3.7" - resolved "https://registry.yarnpkg.com/shellfie/-/shellfie-1.3.7.tgz#b89fda377144e52e43e3ffd366a130e3412d5594" + resolved "https://registry.npmjs.org/shellfie/-/shellfie-1.3.7.tgz" integrity sha512-4l1Co5D7UNHUKkqwy1ko934I8y8gkwayFLvb481uFo423hNaKHwC5m5JnERAtwayq8xpPcLhJ5IUpT0qECRFxw== dependencies: puppeteer latest @@ -945,17 +1023,17 @@ shellfie@^1.3.1: smart-buffer@^4.2.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" + resolved "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz" integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== snaptdout@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/snaptdout/-/snaptdout-2.1.0.tgz#fb2fa3f47a8ef470adc39e2dfeefc3bec2863a81" + resolved "https://registry.npmjs.org/snaptdout/-/snaptdout-2.1.0.tgz" integrity sha512-kqzi5IcBxzDowvSY+l2QFEkKF9jzDPv56M9YPfmD1mYjSzPCyLwdrU6DFDUMU+N36ZQYIWWHeTI9ugPXwXK17g== socks-proxy-agent@^8.0.2: version "8.0.2" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz#5acbd7be7baf18c46a3f293a840109a430a640ad" + resolved "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz" integrity sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g== dependencies: agent-base "^7.0.2" @@ -964,7 +1042,7 @@ socks-proxy-agent@^8.0.2: socks@^2.7.1: version "2.7.1" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55" + resolved "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz" integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ== dependencies: ip "^2.0.0" @@ -972,12 +1050,12 @@ socks@^2.7.1: source-map@~0.6.1: version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== streamx@^2.15.0: version "2.15.6" - resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.15.6.tgz#28bf36997ebc7bf6c08f9eba958735231b833887" + resolved "https://registry.npmjs.org/streamx/-/streamx-2.15.6.tgz" integrity sha512-q+vQL4AAz+FdfT137VF69Cc/APqUbxy+MDOImRrMvchJpigHj9GksgDU2LYbO9rx7RX6osWgxJB2WxhYv4SZAw== dependencies: fast-fifo "^1.1.0" @@ -985,7 +1063,7 @@ streamx@^2.15.0: string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" @@ -994,45 +1072,45 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" strip-json-comments@3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== styl3@^1.2.4: version "1.4.0" - resolved "https://registry.yarnpkg.com/styl3/-/styl3-1.4.0.tgz#e682f87e683cbee8e5d810d76bd35817c5ad8acb" + resolved "https://registry.npmjs.org/styl3/-/styl3-1.4.0.tgz" integrity sha512-RdUDaCy9POYkcAunRcGr+pu1eFcoE4kOQCEpm6Gd0bmTZUXSPzK1dgQOgrNOM9JdAb2/GY2gEUNJN8Hy+mr+8Q== -supports-color@8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - supports-color@^5.3.0: version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" supports-color@^7.1.0: version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + tar-fs@3.0.4: version "3.0.4" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.0.4.tgz#a21dc60a2d5d9f55e0089ccd78124f1d3771dbbf" + resolved "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz" integrity sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w== dependencies: mkdirp-classic "^0.5.2" @@ -1041,7 +1119,7 @@ tar-fs@3.0.4: tar-stream@^3.1.5: version "3.1.7" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-3.1.7.tgz#24b3fb5eabada19fe7338ed6d26e5f7c482e792b" + resolved "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz" integrity sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ== dependencies: b4a "^1.6.4" @@ -1050,34 +1128,58 @@ tar-stream@^3.1.5: through@^2.3.8: version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: is-number "^7.0.0" tr46@~0.0.3: version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +ts-node@10.9.2: + version "10.9.2" + resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + tslib@^2.0.1: version "2.6.2" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== type-detect@^4.0.0, type-detect@^4.0.5: version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== +typescript@>=2.7, typescript@>=4.9.5, typescript@5.4.5: + version "5.4.5" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz" + integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== + unbzip2-stream@1.4.3: version "1.4.3" - resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" + resolved "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz" integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== dependencies: buffer "^5.2.1" @@ -1085,27 +1187,32 @@ unbzip2-stream@1.4.3: undici-types@~5.26.4: version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== universalify@^0.1.0: version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + resolved "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== urlpattern-polyfill@10.0.0: version "10.0.0" - resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz#f0a03a97bfb03cdf33553e5e79a2aadd22cac8ec" + resolved "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz" integrity sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg== +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + webidl-conversions@^3.0.0: version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== whatwg-url@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== dependencies: tr46 "~0.0.3" @@ -1113,12 +1220,12 @@ whatwg-url@^5.0.0: workerpool@6.2.1: version "6.2.1" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" + resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== wrap-ansi@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: ansi-styles "^4.0.0" @@ -1127,47 +1234,42 @@ wrap-ansi@^7.0.0: wrappy@1: version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== ws@8.16.0: version "8.16.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4" + resolved "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz" integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ== xterm-addon-fit@^0.5.0: version "0.5.0" - resolved "https://registry.yarnpkg.com/xterm-addon-fit/-/xterm-addon-fit-0.5.0.tgz#2d51b983b786a97dcd6cde805e700c7f913bc596" + resolved "https://registry.npmjs.org/xterm-addon-fit/-/xterm-addon-fit-0.5.0.tgz" integrity sha512-DsS9fqhXHacEmsPxBJZvfj2la30Iz9xk+UKjhQgnYNkrUIN5CYLbw7WEfz117c7+S86S/tpHPfvNxJsF5/G8wQ== -xterm@^4.14.1: +xterm@^4.0.0, xterm@^4.14.1: version "4.19.0" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.19.0.tgz#c0f9d09cd61de1d658f43ca75f992197add9ef6d" + resolved "https://registry.npmjs.org/xterm/-/xterm-4.19.0.tgz" integrity sha512-c3Cp4eOVsYY5Q839dR5IejghRPpxciGmLWWaP9g+ppfMeBChMeLa1DCA+pmX/jyDZ+zxFOmlJL/82qVdayVoGQ== y18n@^5.0.5: version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== -yargs-parser@20.2.4: +yargs-parser@^20.2.2, yargs-parser@20.2.4: version "20.2.4" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz" integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== -yargs-parser@^20.2.2: - version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== - yargs-parser@^21.1.1: version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== yargs-unparser@2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + resolved "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz" integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== dependencies: camelcase "^6.0.0" @@ -1177,7 +1279,7 @@ yargs-unparser@2.0.0: yargs@16.2.0: version "16.2.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== dependencies: cliui "^7.0.2" @@ -1190,7 +1292,7 @@ yargs@16.2.0: yargs@17.7.2: version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: cliui "^8.0.1" @@ -1203,13 +1305,18 @@ yargs@17.7.2: yauzl@^2.10.0: version "2.10.0" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + resolved "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz" integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g== dependencies: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" +yn@3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + yocto-queue@^0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From e23f9bd240882e04d0e460fe1771dec8ff6f41b8 Mon Sep 17 00:00:00 2001 From: Tal Hayut Date: Thu, 2 May 2024 14:06:15 +0300 Subject: [PATCH 08/18] feat: adding width and height support --- config/config.js | 1 + index.js | 25 ++++++++++++++++--------- pp.js | 7 ++++--- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/config/config.js b/config/config.js index 7caf1a1..1c46297 100644 --- a/config/config.js +++ b/config/config.js @@ -9,6 +9,7 @@ module.exports = { char: '█', naked: false, width: 100, + height: 50, theme: '', structure: { y: '╢', diff --git a/index.js b/index.js index 8ad83b7..059fefc 100644 --- a/index.js +++ b/index.js @@ -9,6 +9,7 @@ class Chartscii { this.options = this.setOptions(options); this.colors = style({ theme: this.options.theme }); this.width = this.options.width; + this.height = this.options.height; this.data = this.sortData(data, this.options.reverse); this.createGraphAxis(); } @@ -132,7 +133,7 @@ class Chartscii { verticalChart() { - const maxHeight = Math.max(...this.data.map(d => this.getScaledValue(getPointValue(d)))); + const maxHeight = Math.max(...this.data.map(d => this.getScaledVerticalValue(getPointValue(d)))); const labelWidths = this.data.map(point => point.labelColorLess); const maxLabelWidth = Math.max(...labelWidths); const barWidth = this.options.barWidth || maxLabelWidth; @@ -140,28 +141,30 @@ class Chartscii { const spaces = []; this.data.forEach((point, index) => { - const value = this.getScaledValue(getPointValue(point)); + const value = this.getScaledVerticalValue(getPointValue(point)); const height = Math.round((value / maxHeight) * maxHeight); const percentageLabel = point.label; const padding = Math.floor((maxLabelWidth - barWidth) / 2); - const label = percentageLabel.padEnd(maxLabelWidth, ' '); + const scaledWidth = Math.round((this.options.width / this.data.length) / 10); + const label = percentageLabel.padEnd(maxLabelWidth + scaledWidth, ' '); for (let i = 0; i < maxHeight; i++) { if (i < maxHeight - height) { if (this.options.fill) { const coloredFillChar = this.options.color ? this.colorify(this.options.fill, this.options.color) : this.options.fill; - verticalChart[i][index] = padLine(padding, coloredFillChar.repeat(barWidth)); + verticalChart[i][index] = padLine(padding + scaledWidth, coloredFillChar.repeat(barWidth)); + } else { + verticalChart[i][index] = padLine(padding + scaledWidth, ' '.repeat(barWidth)); } } else { - const unevenPadding = barWidth % 2 === 0 ? 1 : 0; const coloredChar = this.options.color ? this.colorify(this.options.char, this.options.color) : this.options.char; - verticalChart[i][index] = ' '.repeat(padding + unevenPadding) + coloredChar.repeat(barWidth) + ' '.repeat(padding) + verticalChart[i][index] = ' '.repeat(padding + scaledWidth) + coloredChar.repeat(barWidth) + ' '.repeat(padding + scaledWidth) } } const labelSpace = Math.floor(maxLabelWidth - this.stripAnsi(label).length); const labelPadding = this.options.colorLabels && labelSpace> 0 ? ' '.repeat(labelSpace) : '' - verticalChart[maxHeight][index] = label + labelPadding; + verticalChart[maxHeight][index] = ' '.repeat(scaledWidth) + label + labelPadding; spaces.push(label + labelPadding) }); @@ -288,9 +291,9 @@ class Chartscii { create() { const asciiChart = []; - if (this.options.orientation === 'vertical') { + if (this.options.orientation === 'vertical') { return this.verticalChart(); - } + } if (this.options.label) { asciiChart.push(this.makeChartLabel()); @@ -317,6 +320,10 @@ class Chartscii { return Math.round((value / this.measures.numeric) * this.width); } + getScaledVerticalValue(value) { + return Math.round((value / this.measures.numeric) * (this.height / 10)); + } + get() { return this.chart; } diff --git a/pp.js b/pp.js index 38a678b..d0ab4e7 100644 --- a/pp.js +++ b/pp.js @@ -11,17 +11,18 @@ for (let i = 1; i <= 10; i++) { // create chart const chart = new Chartscii(data, { // label: 'Example Chart', - width: 50, + width: 100, + height: 100, sort: false, reverse: false, - // fill: '░', + fill: '░', char: '█', color: 'red', label: 'THANKS', colorLabels: false, percentage: false, labels: true, - barWidth: 2, + barWidth: 3, naked: false, orientation: 'vertical' }); From 4db530d3f6bde3a549114e9e2d502c61bef3c93e Mon Sep 17 00:00:00 2001 From: Tal Hayut Date: Sun, 5 May 2024 11:31:52 +0300 Subject: [PATCH 09/18] chore: ahhhhh --- config/config.js | 2 +- examples/example.js | 4 +- index.js | 74 +++++++++++----------- pp.js | 12 ++-- ts/charts_scii/formatter.ts | 116 +++++++++++++++++++++++++++++++++++ ts/charts_scii/index.ts | 26 ++++++++ ts/charts_scii/options.ts | 28 +++++++++ ts/charts_scii/processor.ts | 79 ++++++++++++++++++++++++ ts/charts_scii/test.ts | 4 ++ ts/charts_scii/tsconfig.json | 20 ++++++ ts/charts_scii/types.ts | 67 ++++++++++++++++++++ ts/main.ts | 15 ----- 12 files changed, 387 insertions(+), 60 deletions(-) create mode 100644 ts/charts_scii/formatter.ts create mode 100644 ts/charts_scii/index.ts create mode 100644 ts/charts_scii/options.ts create mode 100644 ts/charts_scii/processor.ts create mode 100644 ts/charts_scii/test.ts create mode 100644 ts/charts_scii/tsconfig.json create mode 100644 ts/charts_scii/types.ts diff --git a/config/config.js b/config/config.js index 1c46297..baa06b2 100644 --- a/config/config.js +++ b/config/config.js @@ -9,7 +9,7 @@ module.exports = { char: '█', naked: false, width: 100, - height: 50, + height: 100, theme: '', structure: { y: '╢', diff --git a/examples/example.js b/examples/example.js index 0e76fe1..132a3ee 100644 --- a/examples/example.js +++ b/examples/example.js @@ -14,12 +14,14 @@ const chart = new Chartscii(data, { width: 100, sort: false, reverse: false, - fill: '░', + // fill: '░', char: '█', color: 'green', colorLabels: true, percentage: true, labels: true, + barWidth: 2, + orientation: 'vertical', // naked: true }); diff --git a/index.js b/index.js index 059fefc..a4fdca6 100644 --- a/index.js +++ b/index.js @@ -133,20 +133,20 @@ class Chartscii { verticalChart() { - const maxHeight = Math.max(...this.data.map(d => this.getScaledVerticalValue(getPointValue(d)))); - const labelWidths = this.data.map(point => point.labelColorLess); + const maxHeight = Math.max(...this.chart.map(d => this.getScaledVerticalValue(getPointValue(d)))); + const labelWidths = this.chart.map(point => point.labelColorLess); const maxLabelWidth = Math.max(...labelWidths); const barWidth = this.options.barWidth || maxLabelWidth; - const verticalChart = Array(maxHeight + 1).fill('').map(() => Array(this.data.length).fill(' ').map(() => ' '.repeat(maxLabelWidth))); - const spaces = []; + const verticalSpace = this.options.labels ? 1 : 0; + const verticalChart = Array(maxHeight + verticalSpace).fill('').map(() => Array(this.chart.length).fill(' ').map(() => ' '.repeat(maxLabelWidth))); + const padding = Math.floor((maxLabelWidth - barWidth) / 2); + const scaledWidth = Math.round((this.options.width / this.chart.length) / 10); + const space = []; - this.data.forEach((point, index) => { + this.chart.forEach((point, index) => { const value = this.getScaledVerticalValue(getPointValue(point)); const height = Math.round((value / maxHeight) * maxHeight); - const percentageLabel = point.label; - - const padding = Math.floor((maxLabelWidth - barWidth) / 2); - const scaledWidth = Math.round((this.options.width / this.data.length) / 10); + const percentageLabel = getPointLabel(point); const label = percentageLabel.padEnd(maxLabelWidth + scaledWidth, ' '); for (let i = 0; i < maxHeight; i++) { @@ -160,12 +160,14 @@ class Chartscii { } else { const coloredChar = this.options.color ? this.colorify(this.options.char, this.options.color) : this.options.char; verticalChart[i][index] = ' '.repeat(padding + scaledWidth) + coloredChar.repeat(barWidth) + ' '.repeat(padding + scaledWidth) + space.push((padding + scaledWidth)); } } - const labelSpace = Math.floor(maxLabelWidth - this.stripAnsi(label).length); - const labelPadding = this.options.colorLabels && labelSpace> 0 ? ' '.repeat(labelSpace) : '' - verticalChart[maxHeight][index] = ' '.repeat(scaledWidth) + label + labelPadding; - spaces.push(label + labelPadding) + if (this.options.labels) { + const diff = point.labelColorLess % 2 === 0 ? 1 : 0; + const space = Math.floor((padding + scaledWidth + diff) / 2); + verticalChart[maxHeight][index] = ' '.repeat(space) + label + ' '.repeat(space) + } }); const chart = verticalChart.map(row => { @@ -176,9 +178,9 @@ class Chartscii { }) if (!this.options.naked) { - const removeSpace = this.options.percentage ? 7 : 3; - const width = (this.stripAnsi(spaces[0]).length - removeSpace) * this.data.length; - chart.push([this.makeVerticalChartBottom(width)]) + const width = Math.abs(((barWidth - 1) * this.chart.length) - (this.chart.length * 3)); + console.log({ width, scaledWidth, padding, barWidth }); + chart.push([this.makeVerticalChartBottom(width + (padding * scaledWidth))]) } chart.unshift([this.makeChartLabel()]) @@ -218,13 +220,13 @@ class Chartscii { let labelColorLess = value.toString().length; this.measures.label = this.updateMaxLabelLength(value.toString()); - if (this.options.percentage) { + if (this.options.percentage && this.options.labels) { point.label = this.getPercentageData(value); this.measures.label = this.updateMaxLabelLength(point.label); labelColorLess = point.label.length; } - if (this.options.colorLabels) { + if (this.options.colorLabels && this.options.labels) { const printValue = point.label || value; point.label = this.colorLabel(printValue, color); } @@ -246,21 +248,6 @@ class Chartscii { return sorted; } - makeSpace() { - if (this.measures.space === 2) { - return ' '.repeat(this.measures.space + 1); - } - if (this.measures.space % 2 === 0) { - return ' '.repeat(this.measures.space); - } else if (this.measures.space % 3 === 0) { - return this.measures.space === 3 ? ' ' : ' '.repeat(this.measures.space - 7); - } else if (this.measures.space < 2) { - return ' '.repeat(this.measures.space + 1); - } else { - return ' '.repeat(this.measures.space - 3); - } - } - makeChartLabel() { if (this.options.label) { const space = ' '.repeat(this.measures.space + 1); @@ -275,15 +262,13 @@ class Chartscii { makeChartBottom() { const base = this.options.labels ? ' '.repeat(this.measures.label + 1) + this.options.structure.leftCorner - : ' '.repeat(this.measures.label> 1 ? this.measures.label - 1 : this.measures.label) + this.options.structure.leftCorner; + : ' '.repeat(this.measures.label> 1 ? this.measures.label - 2 : this.measures.label) + this.options.structure.leftCorner; return base + this.options.structure.x.repeat((this.width / 2)) } makeVerticalChartBottom(width = this.width) { - const base = this.options.labels - ? this.options.structure.leftCorner.repeat(1) - : ' '.repeat(this.measures.label> 1 ? this.measures.label - 1 : this.measures.label) + this.options.structure.leftCorner; + const base = this.options.structure.leftCorner.repeat(1) return base + this.options.structure.x.repeat(width) } @@ -332,3 +317,18 @@ class Chartscii { module.exports = Chartscii; +// data processing +// data formatting +// chart creation +// chart formatting +// chart output + +// data processing + // map each data point to an internal type (Point) + // scale the data according to width and height +// data formatting + // format each data point to a string (color, label, percentage) +// chart creation + // create the chart based on width and height +// chart formatting + // format the chart based on options \ No newline at end of file diff --git a/pp.js b/pp.js index d0ab4e7..7ecbe75 100644 --- a/pp.js +++ b/pp.js @@ -4,25 +4,25 @@ const Chartscii = require('./index'); const data = []; for (let i = 1; i <= 10; i++) { - data.push({ value: i + 1, label: `WHAT ${i}` }); + data.push({ value: i + 1, label: `${i}` }); // data.push(i) } // create chart const chart = new Chartscii(data, { // label: 'Example Chart', - width: 100, + width: 80, height: 100, sort: false, reverse: false, - fill: '░', + // fill: '░', char: '█', color: 'red', label: 'THANKS', - colorLabels: false, - percentage: false, + colorLabels: true, + percentage: true, labels: true, - barWidth: 3, + barWidth: 2, naked: false, orientation: 'vertical' }); diff --git a/ts/charts_scii/formatter.ts b/ts/charts_scii/formatter.ts new file mode 100644 index 0000000..03d9cd0 --- /dev/null +++ b/ts/charts_scii/formatter.ts @@ -0,0 +1,116 @@ +import { ChartDataFormatter, ChartOptions, ChartData, ChartPoint } from './types'; +import style from 'styl3'; + +class HorizontalChartFormatter implements ChartDataFormatter { + private options: ChartOptions + private colors: Record; + + constructor(options: ChartOptions) { + this.options = options; + this.colors = style({ theme: this.options.theme }); + } + + colorify(txt: string, color?: string) { + if (color) { + if (color.includes('#')) { + return this.colors.hex(color)`${txt}`; + } else if (color.match(/[0-9]/)) { + return this.colors.ansi(color)`${txt}`; + } else if (Array.isArray(color)) { + return this.colors.rgb(...color)`${txt}`; + } else { + return this.colors[color]`${txt}`; + } + } + } + + formatBottom() { + const space = ' '.repeat(this.options.max.label + 1); + return space + this.options.structure.leftCorner + this.options.structure.x.repeat(this.options.width); + } + + + scaleBar(size: number, bar: string) { + const barHeight = this.options.height / size; + const space = ' '.repeat(this.options.max.label + 2); + const bars = []; + + for (let i = 0; i < barHeight; i++) { + const padding = i === 0 ? '' : space; + bars.push(padding + bar) + } + + return bars.join('\n'); + } + + formatFill(point: ChartPoint) { + if (this.options.fill) { + const diff = (this.options.width * 2) - point.scaled; + return this.options.fill.repeat(diff); + } + + return ''; + } + + formatBar(point: ChartPoint, size: number) { + const value = this.options.char?.repeat(point.scaled) + this.formatFill(point); + const bar = this.scaleBar(size, value); + + return point.color ? this.colorify(bar, point.color) : value; + } + + formatPercentage(point: ChartPoint) { + if (this.options.percentage) { + return ` (${point.percentage.toFixed(2)}%)` + } + + return ''; + } + + formatLabelSpace(point: ChartPoint) { + if (this.options.max?.label) { + const space = this.options.max.label - (point.label.length); + return ' '.repeat(space); + } + + return ''; + } + + formatLabel(point: ChartPoint) { + const percentage = this.formatPercentage(point); + const space = this.formatLabelSpace(point); + const label = this.options.labels ? `${space}${point.label}${percentage}` : ''; + return this.options.colorLabels ? this.colorify(label, this.options.color) : label; + } + + formatLine(_key: string, point: ChartPoint, chart: ChartData) { + const value = this.formatBar(point, chart.size); + const label = this.formatLabel(point); + const key = this.options.structure.y; + + if (this.options.labels) { + return `${this.safeSpace(label)}${key}${value}`; + } + + return `${key}${value}`; + } + + format(chart: ChartData) { + const output = []; + + for (const [key, point] of chart) { + const line = this.formatLine(key, point, chart); + output.push(line); + } + + output.push(this.formatBottom()) + + return output.join('\n'); + } + + safeSpace(text: string) { + return !!text ? text + ' ' : ''; + } +} + +export default HorizontalChartFormatter; \ No newline at end of file diff --git a/ts/charts_scii/index.ts b/ts/charts_scii/index.ts new file mode 100644 index 0000000..17575a2 --- /dev/null +++ b/ts/charts_scii/index.ts @@ -0,0 +1,26 @@ +import HorizontalChartFormatter from './formatter'; +import ChartProcessor from './processor'; +import defaultOptions from './options'; +import { InputData, ChartOptions, ChartData } from './types'; + + +class Chartscii { + private chart: ChartData; + private asciiChart: string; + + constructor(data: InputData[], options?: ChartOptions) { + const config = { ...defaultOptions, ...options }; + const processor = new ChartProcessor(config); + const [chart, processedOptions] = processor.process(data); + + this.chart = chart; + const formatter = new HorizontalChartFormatter(processedOptions); + this.asciiChart = formatter.format(this.chart); + } + + create() { + return this.asciiChart; + } +} + +export default Chartscii; diff --git a/ts/charts_scii/options.ts b/ts/charts_scii/options.ts new file mode 100644 index 0000000..34bb577 --- /dev/null +++ b/ts/charts_scii/options.ts @@ -0,0 +1,28 @@ +import { ChartOptions } from './types'; + +const options: ChartOptions = { + percentage: false, + colorLabels: false, + sort: false, + reverse: false, + color: undefined, + label: '', + labels: true, + char: '█', + naked: false, + width: 50, + height: 50, + theme: '', + max: { + label: 0, + value: 0 + }, + structure: { + y: '╢', + x: '══', + leftCorner: '╚', + noLabelChar: '║' + }, +} + +export default options; \ No newline at end of file diff --git a/ts/charts_scii/processor.ts b/ts/charts_scii/processor.ts new file mode 100644 index 0000000..f51d6f7 --- /dev/null +++ b/ts/charts_scii/processor.ts @@ -0,0 +1,79 @@ +import { ChartDataProcessor, InputData, ChartOptions, ChartData } from './types'; + +class ChartProcessor implements ChartDataProcessor { + private options: ChartOptions; + constructor(options: ChartOptions) { + this.options = options; + } + + calculateData(data: InputData[]): number { + return data.reduce((a, p) => { + const value = typeof p === "number" ? p : p.value + const label = typeof p === "number" ? p.toString() : p.label; + + if (value>= this.options.max.value) { + this.options.max.value = value; + } + if (label.length>= this.options.max.label) { + this.options.max.label = label.length; + } + return a + value; + }, 0); + } + + percentage(value: number, total: number) { + if (this.options.percentage) { + const avg = value / total; + return avg * 100; + } + + return undefined; + } + + scale(value: number) { + if (this.options.max.value && this.options.width) { + return Math.round((value / this.options.max.value) * this.options.width); + } + + return value; + } + + preprocess(data: InputData[]): { processed: InputData[], key: string, total: number } { + const sorted = this.sort(data); + const key = this.options.structure.y; + const total = this.calculateData(data); + return { processed: sorted, key, total } + } + + process(data: InputData[]): [ChartData, ChartOptions] { + if (!Array.isArray(data)) throw new Error("Input data must be an array"); + if (typeof data[0] === "string") throw new Error("Input values must be numbers"); + + const { processed, total } = this.preprocess(data); + const chartData = new Map(); + + processed.forEach((point, i) => { + const { color = this.options.color, label, value } = typeof point === "number" ? { value: point, label: point.toString() } : point; + const formattedPoint = { + label, + value, + color, + scaled: this.scale(value) * 2, + percentage: this.percentage(value, total) + } + chartData.set(i, formattedPoint); + }); + + return [chartData, this.options]; + } + + sort(data: InputData[]): InputData[] { + return data.sort((a, b) => { + const first = typeof a === "number" ? a : a.value; + const second = typeof b === "number" ? b : b.value; + return first - second; + }); + } +} + +export default ChartProcessor; \ No newline at end of file diff --git a/ts/charts_scii/test.ts b/ts/charts_scii/test.ts new file mode 100644 index 0000000..6d46100 --- /dev/null +++ b/ts/charts_scii/test.ts @@ -0,0 +1,4 @@ +import Chartscii from '.'; + +const chart = new Chartscii([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], { color: 'green', width: 50, height: 10, fill: '░', }); +console.log(chart.create()); \ No newline at end of file diff --git a/ts/charts_scii/tsconfig.json b/ts/charts_scii/tsconfig.json new file mode 100644 index 0000000..559b657 --- /dev/null +++ b/ts/charts_scii/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "es2020", // Compile to ECMAScript 2020. Supports modern JS features. + "module": "commonjs", // Use CommonJS module system, suitable for Node.js. + "lib": ["es2020", "dom"], // Include typings for ES2020 and DOM (optional, remove if not manipulating DOM). + "outDir": "./dist", // Output directory for compiled files. + "rootDir": ".", // Root directory of source files. + "strict": false, // Enable all strict type-checking options. + "esModuleInterop": true, // Enables emit interoperability between CommonJS and ES Modules. + "moduleResolution": "node", // Resolve modules using Node.js's module resolution strategy. + "allowJs": true, // Allow JavaScript files to be compiled. + "noImplicitAny": true, // Raise error on expressions and declarations with an implied 'any' type. + // "noImplicitReturns": true, // Report error when not all code paths in function return a value. + // "noUnusedLocals": true, // Report errors on unused local variables. + // "noUnusedParameters": true, // Report errors on unused parameters. + "removeComments": true, // Do not emit comments to output. + "sourceMap": true, // Generates corresponding '.map' file. + "types": ["@types/mocha", "@types/node"] + }, +} diff --git a/ts/charts_scii/types.ts b/ts/charts_scii/types.ts new file mode 100644 index 0000000..f850271 --- /dev/null +++ b/ts/charts_scii/types.ts @@ -0,0 +1,67 @@ +export type Measures = { + numeric: number; + count: number; + label: number; + space: number; +} + +export type ChartOptions = { + sort?: boolean; + percentage?: boolean; + colorLabels?: boolean; + reverse?: boolean; + naked?: boolean; + labels?: boolean; + color?: string; + label?: string; + char?: string; + fill?: string; + width?: number; + height?: number; + theme?: string; + max?: { + label: number; + value: number; + }, + orientation?: 'vertical' | 'horizontal'; + structure?: { + y: string; + x: string; + leftCorner: string; + noLabelChar: string; + }, +} + +// process +export type InputPoint = { + value: number; + color?: string; + label?: string; +} + +export type InputData = InputPoint | number; + +export type ChartPoint = { + label: string; + value: number; + color: string; + scaled: number; + percentage: number; +} + +export type ChartData = Map + +export interface ChartDataProcessor { + process(data: InputData[]): [ChartData, ChartOptions]; + sort(data: InputData[]): InputData[]; +} + +export interface ChartDataFormatter { + format(chart: ChartData): string; +} + + + + + +export type ChartOutput = Map; \ No newline at end of file diff --git a/ts/main.ts b/ts/main.ts index dca1df3..18b907d 100644 --- a/ts/main.ts +++ b/ts/main.ts @@ -190,21 +190,6 @@ class Chartscii { return sorted; } - makeSpace() { - if (this.measures.space === 2) { - return ' '.repeat(this.measures.space + 1); - } - if (this.measures.space % 2 === 0) { - return ' '.repeat(this.measures.space); - } else if (this.measures.space % 3 === 0) { - return this.measures.space === 3 ? ' ' : ' '.repeat(this.measures.space - 7); - } else if (this.measures.space < 2) { - return ' '.repeat(this.measures.space + 1); - } else { - return ' '.repeat(this.measures.space - 3); - } - } - makeChartLabel() { if (this.options.label) { const space = ' '.repeat(this.measures.space + 1); From 265cc4de46460a041c0bedeef10555ef77135d96 Mon Sep 17 00:00:00 2001 From: Tal Hayut Date: Sun, 5 May 2024 15:04:44 +0300 Subject: [PATCH 10/18] chore: whoooa --- ts/charts_scii/formatter.ts | 55 +++++++++++++++++++++++-------------- ts/charts_scii/processor.ts | 28 +++++++++++++------ ts/charts_scii/test.ts | 46 +++++++++++++++++++++++++++++-- 3 files changed, 98 insertions(+), 31 deletions(-) diff --git a/ts/charts_scii/formatter.ts b/ts/charts_scii/formatter.ts index 03d9cd0..49295a3 100644 --- a/ts/charts_scii/formatter.ts +++ b/ts/charts_scii/formatter.ts @@ -24,20 +24,32 @@ class HorizontalChartFormatter implements ChartDataFormatter { } } + reset(text: string) { + return this.colors.reset(text); + } + + formatStructure(structChar: string, color?: string) { + const colored = color || this.options.color; + return this.colors.colors.reset + structChar + this.colors.colors[colored]; + } + formatBottom() { - const space = ' '.repeat(this.options.max.label + 1); + const space = ' '.repeat(this.options.max.label); return space + this.options.structure.leftCorner + this.options.structure.x.repeat(this.options.width); } - scaleBar(size: number, bar: string) { + scaleBar(size: number, bar: string, point: ChartPoint) { const barHeight = this.options.height / size; - const space = ' '.repeat(this.options.max.label + 2); + + const space = point.label.length + (this.options.max.label - point.label.length); + const padding = ' '.repeat(space); const bars = []; for (let i = 0; i < barHeight; i++) { - const padding = i === 0 ? '' : space; - bars.push(padding + bar) + const char = this.formatStructure(this.options.structure.noLabelChar, point.color); + const scaled = i !== 0 ? padding + char : ''; + bars.push(scaled + bar) } return bars.join('\n'); @@ -52,47 +64,50 @@ class HorizontalChartFormatter implements ChartDataFormatter { return ''; } - formatBar(point: ChartPoint, size: number) { + formatBar(point: ChartPoint, size: number, label: string) { const value = this.options.char?.repeat(point.scaled) + this.formatFill(point); - const bar = this.scaleBar(size, value); + const bar = this.scaleBar(size, value, point); return point.color ? this.colorify(bar, point.color) : value; - } + } formatPercentage(point: ChartPoint) { if (this.options.percentage) { - return ` (${point.percentage.toFixed(2)}%)` + return `(${point.percentage.toFixed(2)}%)` } return ''; } - formatLabelSpace(point: ChartPoint) { + formatLabelSpace(label: string) { if (this.options.max?.label) { - const space = this.options.max.label - (point.label.length); + const space = this.options.max.label - (label.length); return ' '.repeat(space); } return ''; } - formatLabel(point: ChartPoint) { + formatLabel(point: ChartPoint, key: string) { const percentage = this.formatPercentage(point); - const space = this.formatLabelSpace(point); - const label = this.options.labels ? `${space}${point.label}${percentage}` : ''; - return this.options.colorLabels ? this.colorify(label, this.options.color) : label; + const label = percentage ? `${point.label} ${percentage}` : point.label; + + const space = this.formatLabelSpace(label); + + const value = this.options.labels ? `${label}${space}${this.formatStructure(key)}` : ''; + + return [this.options.colorLabels ? this.colorify(value, this.options.color) : value, label]; } formatLine(_key: string, point: ChartPoint, chart: ChartData) { - const value = this.formatBar(point, chart.size); - const label = this.formatLabel(point); - const key = this.options.structure.y; + const [label, unformatted] = this.formatLabel(point, this.options.structure.y); + const value = this.formatBar(point, chart.size, unformatted); if (this.options.labels) { - return `${this.safeSpace(label)}${key}${value}`; + return `${label}${value}`; } - return `${key}${value}`; + return `${value}`; } format(chart: ChartData) { diff --git a/ts/charts_scii/processor.ts b/ts/charts_scii/processor.ts index f51d6f7..81504b3 100644 --- a/ts/charts_scii/processor.ts +++ b/ts/charts_scii/processor.ts @@ -6,17 +6,26 @@ class ChartProcessor implements ChartDataProcessor { this.options = options; } + calculateTotal(data: InputData[]): number { + return data.reduce((a, p) => { + const value = typeof p === "number" ? p : p.value; + return a + value; + }, 0); + } + calculateData(data: InputData[]): number { + const total = this.calculateTotal(data); + this.options.max.value = total; + return data.reduce((a, p) => { const value = typeof p === "number" ? p : p.value const label = typeof p === "number" ? p.toString() : p.label; - if (value>= this.options.max.value) { - this.options.max.value = value; - } - if (label.length>= this.options.max.label) { - this.options.max.label = label.length; - } + const percentage = this.percentage(value, total); + const percentageLength = percentage ? percentage.toFixed(2).length + 5 : 0; + const potential = this.options.percentage ? label.length + percentageLength : label.length + 1; + this.options.max.label = potential> this.options.max.label ? potential : this.options.max.label; + return a + value; }, 0); } @@ -32,7 +41,7 @@ class ChartProcessor implements ChartDataProcessor { scale(value: number) { if (this.options.max.value && this.options.width) { - return Math.round((value / this.options.max.value) * this.options.width); + return Math.ceil((value / this.options.max.value) * this.options.width); } return value; @@ -51,14 +60,15 @@ class ChartProcessor implements ChartDataProcessor { const { processed, total } = this.preprocess(data); const chartData = new Map(); - + processed.forEach((point, i) => { const { color = this.options.color, label, value } = typeof point === "number" ? { value: point, label: point.toString() } : point; + const scaledValue = this.scale(value); const formattedPoint = { label, value, color, - scaled: this.scale(value) * 2, + scaled: scaledValue, percentage: this.percentage(value, total) } chartData.set(i, formattedPoint); diff --git a/ts/charts_scii/test.ts b/ts/charts_scii/test.ts index 6d46100..0003317 100644 --- a/ts/charts_scii/test.ts +++ b/ts/charts_scii/test.ts @@ -1,4 +1,46 @@ import Chartscii from '.'; -const chart = new Chartscii([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], { color: 'green', width: 50, height: 10, fill: '░', }); -console.log(chart.create()); \ No newline at end of file +const chart = new Chartscii([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20], + { + color: 'green', + width: 30, + height: 10, + fill: '░', + percentage: true, + colorLabels: true + } +); +console.log(chart.create()); + +// let color = ''; + +// const colors = ['green', +// 'red', +// 'cyan', +// 'pink', +// 'blue', +// 'yellow' +// ]; + +// // generate random chart data +// const data = []; +// let count = 0; + +// for (let i = 1; i <= 20; i++) { + +// color = colors[Math.floor(Math.random() * colors.length)]; +// data.push({ value: Math.floor(Math.random() * 1000) + 1, color, label: `${count++}` }); +// } + +// // create chart +// const chart = new Chartscii(data, { +// label: 'Example Chart', +// width: 80, +// percentage: true, +// reverse: true, +// color: color, +// char: '═', +// colorLabels: true +// }); + +// console.log(chart.create()); \ No newline at end of file From b801f3b67f47ee7558931a165bfbcb315e3e8110 Mon Sep 17 00:00:00 2001 From: Tal Hayut Date: Mon, 6 May 2024 08:31:54 +0300 Subject: [PATCH 11/18] chore: damn son --- ts/{charts_scii => char_ts_cii}/formatter.ts | 95 +- ts/char_ts_cii/index.test.ts | 141 +++ ts/{charts_scii => char_ts_cii}/index.ts | 2 +- ts/{charts_scii => char_ts_cii}/options.ts | 10 +- ts/char_ts_cii/package-lock.json | 1077 +++++++++++++++++ ts/char_ts_cii/package.json | 20 + ts/{charts_scii => char_ts_cii}/processor.ts | 35 +- ts/char_ts_cii/snapshots/index.test.json | 146 +++ ts/char_ts_cii/test.ts | 90 ++ ts/{charts_scii => char_ts_cii}/tsconfig.json | 0 ts/{charts_scii => char_ts_cii}/types.ts | 6 +- ts/charts_scii/test.ts | 46 - 12 files changed, 1558 insertions(+), 110 deletions(-) rename ts/{charts_scii => char_ts_cii}/formatter.ts (69%) create mode 100644 ts/char_ts_cii/index.test.ts rename ts/{charts_scii => char_ts_cii}/index.ts (87%) rename ts/{charts_scii => char_ts_cii}/options.ts (76%) create mode 100644 ts/char_ts_cii/package-lock.json create mode 100644 ts/char_ts_cii/package.json rename ts/{charts_scii => char_ts_cii}/processor.ts (73%) create mode 100644 ts/char_ts_cii/snapshots/index.test.json create mode 100644 ts/char_ts_cii/test.ts rename ts/{charts_scii => char_ts_cii}/tsconfig.json (100%) rename ts/{charts_scii => char_ts_cii}/types.ts (92%) delete mode 100644 ts/charts_scii/test.ts diff --git a/ts/charts_scii/formatter.ts b/ts/char_ts_cii/formatter.ts similarity index 69% rename from ts/charts_scii/formatter.ts rename to ts/char_ts_cii/formatter.ts index 49295a3..4a47d84 100644 --- a/ts/charts_scii/formatter.ts +++ b/ts/char_ts_cii/formatter.ts @@ -24,30 +24,23 @@ class HorizontalChartFormatter implements ChartDataFormatter { } } - reset(text: string) { - return this.colors.reset(text); + pad(space: number) { + return ' '.repeat(space) } - formatStructure(structChar: string, color?: string) { - const colored = color || this.options.color; - return this.colors.colors.reset + structChar + this.colors.colors[colored]; - } - - formatBottom() { - const space = ' '.repeat(this.options.max.label); - return space + this.options.structure.leftCorner + this.options.structure.x.repeat(this.options.width); + reset(text: string) { + return this.colors.reset(text); } scaleBar(size: number, bar: string, point: ChartPoint) { - const barHeight = this.options.height / size; - + const barHeight = Math.round(this.options.height / size); const space = point.label.length + (this.options.max.label - point.label.length); - const padding = ' '.repeat(space); + const padding = this.pad(space); const bars = []; for (let i = 0; i < barHeight; i++) { - const char = this.formatStructure(this.options.structure.noLabelChar, point.color); + const char = this.formatStructure(this.options.structure.axis, point.color); const scaled = i !== 0 ? padding + char : ''; bars.push(scaled + bar) } @@ -55,6 +48,14 @@ class HorizontalChartFormatter implements ChartDataFormatter { return bars.join('\n'); } + formatStructure(structChar: string, color?: string) { + const colored = color || this.options.color; + if (colored) { + return this.colors.colors.reset + structChar + this.colors.colors[colored]; + } + return this.colors.colors.reset + structChar; + } + formatFill(point: ChartPoint) { if (this.options.fill) { const diff = (this.options.width * 2) - point.scaled; @@ -64,13 +65,6 @@ class HorizontalChartFormatter implements ChartDataFormatter { return ''; } - formatBar(point: ChartPoint, size: number, label: string) { - const value = this.options.char?.repeat(point.scaled) + this.formatFill(point); - const bar = this.scaleBar(size, value, point); - - return point.color ? this.colorify(bar, point.color) : value; - } - formatPercentage(point: ChartPoint) { if (this.options.percentage) { return `(${point.percentage.toFixed(2)}%)` @@ -80,39 +74,27 @@ class HorizontalChartFormatter implements ChartDataFormatter { } formatLabelSpace(label: string) { - if (this.options.max?.label) { + if (this.options.max.label) { const space = this.options.max.label - (label.length); - return ' '.repeat(space); + return this.pad(space) } return ''; } - formatLabel(point: ChartPoint, key: string) { - const percentage = this.formatPercentage(point); - const label = percentage ? `${point.label} ${percentage}` : point.label; - - const space = this.formatLabelSpace(label); - - const value = this.options.labels ? `${label}${space}${this.formatStructure(key)}` : ''; - - return [this.options.colorLabels ? this.colorify(value, this.options.color) : value, label]; - } - - formatLine(_key: string, point: ChartPoint, chart: ChartData) { - const [label, unformatted] = this.formatLabel(point, this.options.structure.y); - const value = this.formatBar(point, chart.size, unformatted); - - if (this.options.labels) { - return `${label}${value}`; + formatChartLabel(label: string = '') { + if (this.options.colorLabels) { + return this.colorify(label, this.options.color); } - return `${value}`; + return label; } format(chart: ChartData) { const output = []; + output.push(this.formatChartLabel(this.options.label)); + for (const [key, point] of chart) { const line = this.formatLine(key, point, chart); output.push(line); @@ -123,9 +105,36 @@ class HorizontalChartFormatter implements ChartDataFormatter { return output.join('\n'); } - safeSpace(text: string) { - return !!text ? text + ' ' : ''; + formatLine(_key: string, point: ChartPoint, chart: ChartData) { + const label = this.formatLabel(point, this.options.structure.y); + const value = this.formatBar(point, chart.size); + + return `${label}${value}`; + } + + formatLabel(point: ChartPoint, key: string) { + const percentage = this.formatPercentage(point); + const label = percentage ? `${point.label} ${percentage}` : point.label; + const color = point.color || this.options.color; + const space = this.formatLabelSpace(label); + + const value = this.options.labels ? `${label}${space}${this.formatStructure(key)}` : this.formatStructure(this.options.structure.axis); + + return this.options.colorLabels ? this.colorify(value, color) : value; + } + + formatBar(point: ChartPoint, size: number) { + const value = this.options.char?.repeat(point.scaled) + this.formatFill(point); + const bar = this.scaleBar(size, value, point); + + return point.color ? this.colorify(bar, point.color) : value; + } + + formatBottom() { + const space = this.pad(this.options.max.label); + return space + this.options.structure.bottomLeft + this.options.structure.x.repeat(this.options.max.scaled / 2); } + } export default HorizontalChartFormatter; \ No newline at end of file diff --git a/ts/char_ts_cii/index.test.ts b/ts/char_ts_cii/index.test.ts new file mode 100644 index 0000000..6535d5d --- /dev/null +++ b/ts/char_ts_cii/index.test.ts @@ -0,0 +1,141 @@ +import chai from 'chai'; +const expect = chai.expect; +import Chartscii from '.'; +import snap from 'snaptdout'; +const colors = [ + 'red', + 'green', + 'yellow', + 'blue', + 'purple', + 'pink', + 'cyan', + 'orange', +]; + +function generateChartData() { + const data = []; + for (let i = 0; i < colors.length; i++) { + const color = colors[i]; + data.push({ value: i + 1, label: color, color }); + } + return data; +} + +describe('chartscii tests', () => { + let data, chart: any; + + // beforeEach(() => { + // data = [...Array(10).keys()]; + // chart = new Chartscii(data); + // }); + + // it('should initialize chart array with all values', () => { + // const result = chart.get(); + // expect(result.length).to.equal(10); + // }); + + // it('should support 0 values', () => { + // const result = chart.get(); + // expect(result[0]).to.include({ value: '0' }); + // }); + + it('should support { value }', () => { + const data = [...Array(10).keys()].map((key) => { + return { value: key }; + }); + chart = new Chartscii(data); + const result = [...chart.chart.values()][0] + expect(result.value).to.equal(0); + }); + + it('should support { value, label }', () => { + let counter = 0; + const data = [...Array(10).keys()].map((key) => { + return { value: key, label: `label ${counter++}` }; + }); + chart = new Chartscii(data); + const result = [...chart.chart.values()][0] + expect(result.label).to.equal('label 0'); + }); + + it('should support percentage', () => { + let counter = 0; + const data = [...Array(10).keys()].map((key) => { + return { value: key + 1, label: `label ${counter++}` }; + }); + chart = new Chartscii(data, { percentage: true }); + const result = [...chart.chart.values()][0]; + expect(result.percentage).to.equal(1.8181818181818181); + }); +}); + +describe('examples', () => { + it('should match example', async () => { + const data = []; + for (let i = 0; i < 20; i++) { + data.push({ value: i + 1, label: `label ${i}` }); + } + const chart = new Chartscii(data, { color: 'pink', colorLabels: true }); + await snap(chart.create(), 'chart'); + }); + it('should support percentage', async () => { + const data = []; + for (let i = 0; i < 20; i++) { + data.push({ value: i + 1, label: `label ${i}` }); + } + const chart = new Chartscii(data, { + color: 'pink', + colorLabels: true, + percentage: true, + }); + await snap(chart.create(), 'percentage'); + }); + + it('should support labeless chart', async () => { + const data = []; + for (let i = 0; i < 20; i++) { + data.push(i + 1); + } + const chart = new Chartscii(data, { labels: false }); + await snap(chart.create(), 'labeless chart'); + }); + + it('should support labeless colorful chart', async () => { + const data = []; + for (let i = 0; i < colors.length; i++) { + const color = colors[i]; + data.push({ value: i + 1, color }); + } + const chart = new Chartscii(data, { labels: false }); + await snap(chart.create(), 'labeless color chart'); + }); + + it('should support pastel theme', async () => { + const data = generateChartData(); + const chart = new Chartscii(data, { theme: 'pastel', colorLabels: true }); + await snap(chart.create(), 'pastel theme'); + }); + + it('should support lush theme', async () => { + const data = generateChartData(); + const chart = new Chartscii(data, { theme: 'lush', colorLabels: true }); + await snap(chart.create(), 'lush theme'); + }); + it('should support standard theme', async () => { + const data = generateChartData(); + const chart = new Chartscii(data, { theme: 'standard', colorLabels: true }); + await snap(chart.create(), 'standard theme'); + }); + it('should support beach theme', async () => { + const data = generateChartData(); + const chart = new Chartscii(data, { theme: 'beach', colorLabels: true }); + await snap(chart.create(), 'beach theme'); + }); + it('should support default theme', async () => { + const data = generateChartData(); + const chart = new Chartscii(data, { colorLabels: true }); + await snap(chart.create(), 'default theme'); + }); + +}); diff --git a/ts/charts_scii/index.ts b/ts/char_ts_cii/index.ts similarity index 87% rename from ts/charts_scii/index.ts rename to ts/char_ts_cii/index.ts index 17575a2..59c3774 100644 --- a/ts/charts_scii/index.ts +++ b/ts/char_ts_cii/index.ts @@ -9,7 +9,7 @@ class Chartscii { private asciiChart: string; constructor(data: InputData[], options?: ChartOptions) { - const config = { ...defaultOptions, ...options }; + const config = { ...defaultOptions, ...options, ...{ max: { label: 0, value: 0, scaled: 0 } } }; const processor = new ChartProcessor(config); const [chart, processedOptions] = processor.process(data); diff --git a/ts/charts_scii/options.ts b/ts/char_ts_cii/options.ts similarity index 76% rename from ts/charts_scii/options.ts rename to ts/char_ts_cii/options.ts index 34bb577..e45173f 100644 --- a/ts/charts_scii/options.ts +++ b/ts/char_ts_cii/options.ts @@ -11,17 +11,19 @@ const options: ChartOptions = { char: '█', naked: false, width: 50, - height: 50, + height: 10, theme: '', max: { label: 0, - value: 0 + value: 0, + scaled: 0 }, structure: { y: '╢', x: '══', - leftCorner: '╚', - noLabelChar: '║' + bottomLeft: '╚', + axis: '║', + topLeft: '╔' }, } diff --git a/ts/char_ts_cii/package-lock.json b/ts/char_ts_cii/package-lock.json new file mode 100644 index 0000000..06382dd --- /dev/null +++ b/ts/char_ts_cii/package-lock.json @@ -0,0 +1,1077 @@ +{ + "name": "char_ts_cii", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "char_ts_cii", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "@types/mocha": "10.0.6", + "mocha": "10.4.0", + "snaptdout": "2.1.0", + "ts-node": "10.9.2", + "typescript": "5.4.5" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@types/mocha": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", + "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.12.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.8.tgz", + "integrity": "sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==", + "dev": true, + "peer": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 ||>=11.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* ||>= 10.*" + } + }, + "node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", + "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==", + "dev": true, + "dependencies": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "8.1.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/snaptdout": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/snaptdout/-/snaptdout-2.1.0.tgz", + "integrity": "sha512-kqzi5IcBxzDowvSY+l2QFEkKF9jzDPv56M9YPfmD1mYjSzPCyLwdrU6DFDUMU+N36ZQYIWWHeTI9ugPXwXK17g==", + "dev": true + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, + "peer": true + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/ts/char_ts_cii/package.json b/ts/char_ts_cii/package.json new file mode 100644 index 0000000..3e62436 --- /dev/null +++ b/ts/char_ts_cii/package.json @@ -0,0 +1,20 @@ +{ + "name": "char_ts_cii", + "version": "1.0.0", + "description": "", + "main": "index.ts", + "scripts": { + "test": "mocha -r ts-node/register index.test.ts --timeout 50000", + "print": "node -e \"const keys = require('./snapshots/index.test'); Object.keys(keys).map(key => console.log(key + '\\n' + keys[key].join('\\n'))) \" " + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@types/mocha": "10.0.6", + "mocha": "10.4.0", + "snaptdout": "2.1.0", + "ts-node": "10.9.2", + "typescript": "5.4.5" + } +} diff --git a/ts/charts_scii/processor.ts b/ts/char_ts_cii/processor.ts similarity index 73% rename from ts/charts_scii/processor.ts rename to ts/char_ts_cii/processor.ts index 81504b3..cef47b5 100644 --- a/ts/charts_scii/processor.ts +++ b/ts/char_ts_cii/processor.ts @@ -15,16 +15,23 @@ class ChartProcessor implements ChartDataProcessor { calculateData(data: InputData[]): number { const total = this.calculateTotal(data); - this.options.max.value = total; return data.reduce((a, p) => { const value = typeof p === "number" ? p : p.value - const label = typeof p === "number" ? p.toString() : p.label; + const label = typeof p === "number" ? p.toString() : (p.label || p.value.toString()); + + this.options.max.value = value>= this.options.max.value ? value : this.options.max.value; + + const scaledValue = this.scale(value); + this.options.max.scaled = scaledValue>= this.options.max.scaled ? scaledValue : this.options.max.scaled; const percentage = this.percentage(value, total); const percentageLength = percentage ? percentage.toFixed(2).length + 5 : 0; const potential = this.options.percentage ? label.length + percentageLength : label.length + 1; - this.options.max.label = potential> this.options.max.label ? potential : this.options.max.label; + + if (this.options.labels) { + this.options.max.label = potential> this.options.max.label ? potential : this.options.max.label; + } return a + value; }, 0); @@ -40,11 +47,7 @@ class ChartProcessor implements ChartDataProcessor { } scale(value: number) { - if (this.options.max.value && this.options.width) { - return Math.ceil((value / this.options.max.value) * this.options.width); - } - - return value; + return Math.round((value / this.options.max.value) * this.options.width); } preprocess(data: InputData[]): { processed: InputData[], key: string, total: number } { @@ -65,7 +68,7 @@ class ChartProcessor implements ChartDataProcessor { const { color = this.options.color, label, value } = typeof point === "number" ? { value: point, label: point.toString() } : point; const scaledValue = this.scale(value); const formattedPoint = { - label, + label: label || value.toString(), value, color, scaled: scaledValue, @@ -78,11 +81,15 @@ class ChartProcessor implements ChartDataProcessor { } sort(data: InputData[]): InputData[] { - return data.sort((a, b) => { - const first = typeof a === "number" ? a : a.value; - const second = typeof b === "number" ? b : b.value; - return first - second; - }); + if (this.options.sort) { + return data.sort((a, b) => { + const first = typeof a === "number" ? a : a.value; + const second = typeof b === "number" ? b : b.value; + return first - second; + }); + } + + return data; } } diff --git a/ts/char_ts_cii/snapshots/index.test.json b/ts/char_ts_cii/snapshots/index.test.json new file mode 100644 index 0000000..c1bdacd --- /dev/null +++ b/ts/char_ts_cii/snapshots/index.test.json @@ -0,0 +1,146 @@ +{ + "chart": [ + "\u001b[38;5;219m\u001b[0m", + "\u001b[38;5;219mlabel 0 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███\u001b[0m", + "\u001b[38;5;219mlabel 1 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████\u001b[0m", + "\u001b[38;5;219mlabel 2 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████\u001b[0m", + "\u001b[38;5;219mlabel 3 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████\u001b[0m", + "\u001b[38;5;219mlabel 4 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████\u001b[0m", + "\u001b[38;5;219mlabel 5 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████\u001b[0m", + "\u001b[38;5;219mlabel 6 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████\u001b[0m", + "\u001b[38;5;219mlabel 7 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 8 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 9 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 10 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 11 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 12 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 13 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 14 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 15 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 16 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 17 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 18 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 19 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████████████████████████\u001b[0m", + " ╚══════════════════════════════════════════════════" + ], + "percentage": [ + "\u001b[38;5;219m\u001b[0m", + "\u001b[38;5;219mlabel 0 (0.48%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███\u001b[0m", + "\u001b[38;5;219mlabel 1 (0.95%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████\u001b[0m", + "\u001b[38;5;219mlabel 2 (1.43%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████\u001b[0m", + "\u001b[38;5;219mlabel 3 (1.90%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████\u001b[0m", + "\u001b[38;5;219mlabel 4 (2.38%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████\u001b[0m", + "\u001b[38;5;219mlabel 5 (2.86%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████\u001b[0m", + "\u001b[38;5;219mlabel 6 (3.33%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████\u001b[0m", + "\u001b[38;5;219mlabel 7 (3.81%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 8 (4.29%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 9 (4.76%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 10 (5.24%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 11 (5.71%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 12 (6.19%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 13 (6.67%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 14 (7.14%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 15 (7.62%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 16 (8.10%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 17 (8.57%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 18 (9.05%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 19 (9.52%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████████████████████████\u001b[0m", + " ╚══════════════════════════════════════════════════" + ], + "labeless chart": [ + "", + "\u001b[0m║███", + "\u001b[0m║█████", + "\u001b[0m║████████", + "\u001b[0m║██████████", + "\u001b[0m║█████████████", + "\u001b[0m║███████████████", + "\u001b[0m║██████████████████", + "\u001b[0m║████████████████████", + "\u001b[0m║███████████████████████", + "\u001b[0m║█████████████████████████", + "\u001b[0m║████████████████████████████", + "\u001b[0m║██████████████████████████████", + "\u001b[0m║█████████████████████████████████", + "\u001b[0m║███████████████████████████████████", + "\u001b[0m║██████████████████████████████████████", + "\u001b[0m║████████████████████████████████████████", + "\u001b[0m║███████████████████████████████████████████", + "\u001b[0m║█████████████████████████████████████████████", + "\u001b[0m║████████████████████████████████████████████████", + "\u001b[0m║██████████████████████████████████████████████████", + "╚══════════════════════════════════════════════════" + ], + "labeless color chart": [ + "", + "\u001b[0m║\u001b[38;5;160m██████\u001b[0m", + "\u001b[0m║\u001b[32m█████████████\u001b[0m", + "\u001b[0m║\u001b[38;5;227m███████████████████\u001b[0m", + "\u001b[0m║\u001b[34m█████████████████████████\u001b[0m", + "\u001b[0m║\u001b[35m███████████████████████████████\u001b[0m", + "\u001b[0m║\u001b[38;5;219m██████████████████████████████████████\u001b[0m", + "\u001b[0m║\u001b[96m████████████████████████████████████████████\u001b[0m", + "\u001b[0m║\u001b[38;5;215m██████████████████████████████████████████████████\u001b[0m", + "╚══════════════════════════════════════════════════" + ], + "pastel theme": [ + "", + "\u001b[31mred \u001b[0m╢\u001b[0m\u001b[31m██████\u001b[0m", + "\u001b[38;5;49mgreen \u001b[0m╢\u001b[0m\u001b[38;5;49m█████████████\u001b[0m", + "\u001b[38;5;228myellow \u001b[0m╢\u001b[0m\u001b[38;5;228m███████████████████\u001b[0m", + "\u001b[38;5;39mblue \u001b[0m╢\u001b[0m\u001b[38;5;39m█████████████████████████\u001b[0m", + "\u001b[38;5;147mpurple \u001b[0m╢\u001b[0m\u001b[38;5;147m███████████████████████████████\u001b[0m", + "\u001b[38;5;219mpink \u001b[0m╢\u001b[0m\u001b[38;5;219m██████████████████████████████████████\u001b[0m", + "\u001b[38;5;159mcyan \u001b[0m╢\u001b[0m\u001b[38;5;159m████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;209morange \u001b[0m╢\u001b[0m\u001b[38;5;209m██████████████████████████████████████████████████\u001b[0m", + " ╚══════════════════════════════════════════════════" + ], + "lush theme": [ + "", + "\u001b[38;5;196mred \u001b[0m╢\u001b[0m\u001b[38;5;196m██████\u001b[0m", + "\u001b[38;5;154mgreen \u001b[0m╢\u001b[0m\u001b[38;5;154m█████████████\u001b[0m", + "\u001b[38;5;226myellow \u001b[0m╢\u001b[0m\u001b[38;5;226m███████████████████\u001b[0m", + "\u001b[38;5;57mblue \u001b[0m╢\u001b[0m\u001b[38;5;57m█████████████████████████\u001b[0m", + "\u001b[38;5;128mpurple \u001b[0m╢\u001b[0m\u001b[38;5;128m███████████████████████████████\u001b[0m", + "\u001b[38;5;198mpink \u001b[0m╢\u001b[0m\u001b[38;5;198m██████████████████████████████████████\u001b[0m", + "\u001b[38;5;87mcyan \u001b[0m╢\u001b[0m\u001b[38;5;87m████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;202morange \u001b[0m╢\u001b[0m\u001b[38;5;202m██████████████████████████████████████████████████\u001b[0m", + " ╚══════════════════════════════════════════════════" + ], + "standard theme": [ + "", + "\u001b[38;5;9mred \u001b[0m╢\u001b[0m\u001b[38;5;9m██████\u001b[0m", + "\u001b[38;5;10mgreen \u001b[0m╢\u001b[0m\u001b[38;5;10m█████████████\u001b[0m", + "\u001b[38;5;11myellow \u001b[0m╢\u001b[0m\u001b[38;5;11m███████████████████\u001b[0m", + "\u001b[38;5;27mblue \u001b[0m╢\u001b[0m\u001b[38;5;27m█████████████████████████\u001b[0m", + "\u001b[38;5;105mpurple \u001b[0m╢\u001b[0m\u001b[38;5;105m███████████████████████████████\u001b[0m", + "\u001b[38;5;200mpink \u001b[0m╢\u001b[0m\u001b[38;5;200m██████████████████████████████████████\u001b[0m", + "\u001b[38;5;123mcyan \u001b[0m╢\u001b[0m\u001b[38;5;123m████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;214morange \u001b[0m╢\u001b[0m\u001b[38;5;214m██████████████████████████████████████████████████\u001b[0m", + " ╚══════════════════════════════════════════════════" + ], + "beach theme": [ + "", + "\u001b[38;2;254;74;73mred \u001b[0m╢\u001b[0m\u001b[38;2;254;74;73m██████\u001b[0m", + "\u001b[38;2;42;183;202mgreen \u001b[0m╢\u001b[0m\u001b[38;2;42;183;202m█████████████\u001b[0m", + "\u001b[38;2;254;215;102myellow \u001b[0m╢\u001b[0m\u001b[38;2;254;215;102m███████████████████\u001b[0m", + "\u001b[38;2;146;196;238mblue \u001b[0m╢\u001b[0m\u001b[38;2;146;196;238m█████████████████████████\u001b[0m", + "\u001b[38;2;130;119;249mpurple \u001b[0m╢\u001b[0m\u001b[38;2;130;119;249m███████████████████████████████\u001b[0m", + "\u001b[38;2;222;82;133mpink \u001b[0m╢\u001b[0m\u001b[38;2;222;82;133m██████████████████████████████████████\u001b[0m", + "\u001b[38;2;0;255;255mcyan \u001b[0m╢\u001b[0m\u001b[38;2;0;255;255m████████████████████████████████████████████\u001b[0m", + "\u001b[38;2;247;126;2morange \u001b[0m╢\u001b[0m\u001b[38;2;247;126;2m██████████████████████████████████████████████████\u001b[0m", + " ╚══════════════════════════════════════════════════" + ], + "default theme": [ + "", + "\u001b[38;5;160mred \u001b[0m╢\u001b[0m\u001b[38;5;160m██████\u001b[0m", + "\u001b[32mgreen \u001b[0m╢\u001b[0m\u001b[32m█████████████\u001b[0m", + "\u001b[38;5;227myellow \u001b[0m╢\u001b[0m\u001b[38;5;227m███████████████████\u001b[0m", + "\u001b[34mblue \u001b[0m╢\u001b[0m\u001b[34m█████████████████████████\u001b[0m", + "\u001b[35mpurple \u001b[0m╢\u001b[0m\u001b[35m███████████████████████████████\u001b[0m", + "\u001b[38;5;219mpink \u001b[0m╢\u001b[0m\u001b[38;5;219m██████████████████████████████████████\u001b[0m", + "\u001b[96mcyan \u001b[0m╢\u001b[0m\u001b[96m████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;215morange \u001b[0m╢\u001b[0m\u001b[38;5;215m██████████████████████████████████████████████████\u001b[0m", + " ╚══════════════════════════════════════════════════" + ] +} \ No newline at end of file diff --git a/ts/char_ts_cii/test.ts b/ts/char_ts_cii/test.ts new file mode 100644 index 0000000..4413741 --- /dev/null +++ b/ts/char_ts_cii/test.ts @@ -0,0 +1,90 @@ +import Chartscii from '.'; +const colors = [ + 'red', + 'green', + 'yellow', + 'blue', + 'purple', + 'pink', + 'cyan', + 'orange', +]; + +const data = []; +for (let i = 0; i < colors.length; i++) { + const color = colors[i]; + data.push({ value: i + 1, color }); +} +const chart = new Chartscii(data, { labels: false, width: 100, height: 15 }); + +console.log(chart.create()); + +// const data = Array(10).fill(null).map((_, i) => ({ label: `label ${i}`, value: i })) +// const chart = new Chartscii(data, +// { +// color: 'green', +// width: 50, +// height: 10, +// fill: '░', +// sort: false, +// percentage: true, +// colorLabels: true +// } +// ); +// console.log(chart.create()); +// const data = []; +// let count = 0; + +// for (let i = 1; i <= 20; i++) { +// const value = Math.floor(Math.random() * 1000) + 1; +// data.push({ value, label: `label ${count++}`, color: value> 200 ? 'green' : 'red' }); +// } + +// // create chart +// const chart = new Chartscii(data, { +// label: 'Conditional Colors', +// color: 'green', +// width: 50, +// sort: false, +// reverse: false, +// char: 'しかく', +// colorLabels: true, +// percentage: true, +// labels: true +// }); + +// console.log(chart.create()) + + +// let color = ''; + +// const colors = ['green', +// 'red', +// 'cyan', +// 'pink', +// 'blue', +// 'yellow' +// ]; + +// generate random chart data +// const data = []; +// let count = 0; + +// for (let i = 1; i <= 20; i++) { + +// color = colors[Math.floor(Math.random() * colors.length)]; +// data.push({ value: Math.floor(Math.random() * 1000) + 1, color, label: `${count++}` }); +// } + +// // create chart +// const chart = new Chartscii(data, { +// label: 'Example Chart', +// width: 50, +// percentage: true, +// reverse: true, +// color: color, +// char: '═', +// colorLabels: true +// }); + +// console.log(chart.create()); \ No newline at end of file diff --git a/ts/charts_scii/tsconfig.json b/ts/char_ts_cii/tsconfig.json similarity index 100% rename from ts/charts_scii/tsconfig.json rename to ts/char_ts_cii/tsconfig.json diff --git a/ts/charts_scii/types.ts b/ts/char_ts_cii/types.ts similarity index 92% rename from ts/charts_scii/types.ts rename to ts/char_ts_cii/types.ts index f850271..530d4a2 100644 --- a/ts/charts_scii/types.ts +++ b/ts/char_ts_cii/types.ts @@ -22,13 +22,15 @@ export type ChartOptions = { max?: { label: number; value: number; + scaled: number; }, orientation?: 'vertical' | 'horizontal'; structure?: { y: string; x: string; - leftCorner: string; - noLabelChar: string; + bottomLeft: string; + topLeft: string; + axis: string; }, } diff --git a/ts/charts_scii/test.ts b/ts/charts_scii/test.ts deleted file mode 100644 index 0003317..0000000 --- a/ts/charts_scii/test.ts +++ /dev/null @@ -1,46 +0,0 @@ -import Chartscii from '.'; - -const chart = new Chartscii([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20], - { - color: 'green', - width: 30, - height: 10, - fill: '░', - percentage: true, - colorLabels: true - } -); -console.log(chart.create()); - -// let color = ''; - -// const colors = ['green', -// 'red', -// 'cyan', -// 'pink', -// 'blue', -// 'yellow' -// ]; - -// // generate random chart data -// const data = []; -// let count = 0; - -// for (let i = 1; i <= 20; i++) { - -// color = colors[Math.floor(Math.random() * colors.length)]; -// data.push({ value: Math.floor(Math.random() * 1000) + 1, color, label: `${count++}` }); -// } - -// // create chart -// const chart = new Chartscii(data, { -// label: 'Example Chart', -// width: 80, -// percentage: true, -// reverse: true, -// color: color, -// char: '═', -// colorLabels: true -// }); - -// console.log(chart.create()); \ No newline at end of file From 139bb0bcd3961e8f50cd7d1bfa098491e062665d Mon Sep 17 00:00:00 2001 From: Tal Hayut Date: Mon, 6 May 2024 08:36:02 +0300 Subject: [PATCH 12/18] fix: tests --- ts/char_ts_cii/index.test.ts | 24 ++++++++++++------------ ts/char_ts_cii/processor.ts | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ts/char_ts_cii/index.test.ts b/ts/char_ts_cii/index.test.ts index 6535d5d..5673d50 100644 --- a/ts/char_ts_cii/index.test.ts +++ b/ts/char_ts_cii/index.test.ts @@ -25,20 +25,20 @@ function generateChartData() { describe('chartscii tests', () => { let data, chart: any; - // beforeEach(() => { - // data = [...Array(10).keys()]; - // chart = new Chartscii(data); - // }); + beforeEach(() => { + data = [...Array(10).keys()]; + chart = new Chartscii(data); + }); - // it('should initialize chart array with all values', () => { - // const result = chart.get(); - // expect(result.length).to.equal(10); - // }); + it('should initialize chart array with all values', () => { + const result = [...chart.chart.values()]; + expect(result.length).to.equal(10); + }); - // it('should support 0 values', () => { - // const result = chart.get(); - // expect(result[0]).to.include({ value: '0' }); - // }); + it('should support 0 values', () => { + const result = [...chart.chart.values()][0] + expect(result).to.deep.equal({ value: 0, color: undefined, label: '0', scaled: 0, percentage: 0 }); + }); it('should support { value }', () => { const data = [...Array(10).keys()].map((key) => { diff --git a/ts/char_ts_cii/processor.ts b/ts/char_ts_cii/processor.ts index cef47b5..6134031 100644 --- a/ts/char_ts_cii/processor.ts +++ b/ts/char_ts_cii/processor.ts @@ -43,7 +43,7 @@ class ChartProcessor implements ChartDataProcessor { return avg * 100; } - return undefined; + return 0; } scale(value: number) { From aaafca7300057653f4c77fdb103ba2af90c04bd8 Mon Sep 17 00:00:00 2001 From: Tal Hayut Date: Mon, 6 May 2024 15:31:08 +0300 Subject: [PATCH 13/18] fix: my oh my --- .../horizontal.ts} | 8 +- ts/char_ts_cii/formatters/vertical.ts | 147 ++++++++++++++++++ ts/char_ts_cii/index.ts | 9 +- ts/char_ts_cii/options.ts | 1 + ts/char_ts_cii/{ => processor}/processor.ts | 5 +- ts/char_ts_cii/test.ts | 21 ++- ts/char_ts_cii/types.ts | 7 +- 7 files changed, 181 insertions(+), 17 deletions(-) rename ts/char_ts_cii/{formatter.ts => formatters/horizontal.ts} (94%) create mode 100644 ts/char_ts_cii/formatters/vertical.ts rename ts/char_ts_cii/{ => processor}/processor.ts (94%) diff --git a/ts/char_ts_cii/formatter.ts b/ts/char_ts_cii/formatters/horizontal.ts similarity index 94% rename from ts/char_ts_cii/formatter.ts rename to ts/char_ts_cii/formatters/horizontal.ts index 4a47d84..5d96342 100644 --- a/ts/char_ts_cii/formatter.ts +++ b/ts/char_ts_cii/formatters/horizontal.ts @@ -1,7 +1,7 @@ -import { ChartDataFormatter, ChartOptions, ChartData, ChartPoint } from './types'; +import { HorizontalChartDataFormatter, ChartOptions, ChartData, ChartPoint } from '../types'; import style from 'styl3'; -class HorizontalChartFormatter implements ChartDataFormatter { +class HorizontalChartFormatter implements HorizontalChartDataFormatter { private options: ChartOptions private colors: Record; @@ -28,10 +28,6 @@ class HorizontalChartFormatter implements ChartDataFormatter { return ' '.repeat(space) } - reset(text: string) { - return this.colors.reset(text); - } - scaleBar(size: number, bar: string, point: ChartPoint) { const barHeight = Math.round(this.options.height / size); diff --git a/ts/char_ts_cii/formatters/vertical.ts b/ts/char_ts_cii/formatters/vertical.ts new file mode 100644 index 0000000..3c83d11 --- /dev/null +++ b/ts/char_ts_cii/formatters/vertical.ts @@ -0,0 +1,147 @@ +import { VerticalChartDataFormatter, ChartOptions, ChartData, ChartPoint } from '../types'; +import style from 'styl3'; + +class VerticalChartFormatter implements VerticalChartDataFormatter { + private chart: ChartPoint[]; + private options: ChartOptions; + private colors: Record; + + constructor(chart: ChartData, options: ChartOptions) { + this.chart = [...chart.values()] + this.options = options; + this.colors = style({ theme: this.options.theme }); + } + + public format(): string { + const maxHeight = this.getMaxHeight(); + + const barWidth = this.options.barWidth || this.getMaxLabelWidth() || 1; + const verticalSpace = this.options.labels ? 1 : 0; + + const avg = Math.round(this.options.width / this.chart.length); + const median = Math.floor(avg - barWidth); + const scaledWidth = Math.floor(median / barWidth); + + const space = Math.round((avg - barWidth) / 2); + const padding = space> 0 ? space : 0; + + const diff = padding ? (avg - padding - barWidth) : 0; + + const verticalChart = this.initializeVerticalChart(maxHeight, padding, verticalSpace); + + this.populateChart(verticalChart, maxHeight, padding + diff, scaledWidth, barWidth); + return this.composeFinalChart(verticalChart, barWidth, padding, diff); + } + + colorify(txt: string, color?: string) { + if (color) { + if (color.includes('#')) { + return this.colors.hex(color)`${txt}`; + } else if (color.match(/[0-9]/)) { + return this.colors.ansi(color)`${txt}`; + } else if (Array.isArray(color)) { + return this.colors.rgb(...color)`${txt}`; + } else { + return this.colors[color]`${txt}`; + } + } + } + + private getMaxHeight(): number { + return this.options.max.scaled; + } + + private getMaxLabelWidth(): number { + if (this.options.labels) { + const labelWidths = this.chart.map(point => point.label.length); + return Math.max(...labelWidths); + } + + return 0; + } + + private initializeVerticalChart(maxHeight: number, padding: number, verticalSpace: number): string[][] { + return Array(maxHeight + verticalSpace).fill('').map(() => Array(this.chart.length).fill('').map(() => ' '.repeat(padding))); + } + + private populateChart(verticalChart: string[][], maxHeight: number, padding: number, scaledWidth: number, barWidth: number): void { + this.chart.forEach((point, index) => { + const value = point.scaled; + const height = Math.round((value / maxHeight) * maxHeight); + const color = point.color; + + for (let i = 0; i < maxHeight; i++) { + const spaces = this.formatSpace(barWidth, padding); + const bars = this.formatBar(barWidth, padding, color); + const fill = this.formatFill(barWidth, padding, color); + const fills = this.options.fill ? fill : spaces; + + if (i < maxHeight - height) { + verticalChart[i][index] = fills; + } else { + verticalChart[i][index] = bars; + } + } + + // if (this.options.labels) { + // const label = this.getLabel(maxLabelWidth, padding, scaledWidth, point); + // verticalChart[maxHeight][index] = label; + // } + }); + } + + private formatSpace(barWidth: number, padding: number): string { + const character = ' '; + return character.repeat(barWidth) + ' '.repeat(padding); + } + + private formatBar(barWidth: number, padding: number, color: string): string { + const character = this.options.char; + const value = character.repeat(barWidth) + ' '.repeat(padding); + return color ? this.colorify(value, color) : value; + } + + private formatFill(barWidth: number, padding: number, color: string): string { + const character = this.options.fill; + if (this.options.fill) { + const value = character.repeat(barWidth) + ' '.repeat(padding); + return color ? this.colorify(value, color) : value; + } + } + + private getLabel(maxLabelWidth: number, padding: number, scaledWidth: number, point: ChartPoint): string { + const label = point.label.padEnd(maxLabelWidth + scaledWidth, ' '); + return ' '.repeat(padding + scaledWidth) + label + ' '.repeat(padding + scaledWidth); + } + + private composeFinalChart(verticalChart: string[][], barWidth: number, padding: number, avg: number): string { + const chart = verticalChart.map(row => { + if (!this.options.naked) { + return this.options.structure.axis + ' ' + row.join('') + } + return row.join('') + }) + + if (!this.options.naked) { + chart.unshift(this.makeChartLabel()); + chart.push(this.makeVerticalChartBottom(barWidth, padding, avg, verticalChart[verticalChart.length - 1])); + } + return chart.join('\n'); + } + + private makeChartLabel(): string { + return this.options.label; + } + + private makeVerticalChartBottom(barWidth: number, padding: number, avg: number, lastRow: string[]): string { + return this.options.structure.bottomLeft + this.options.structure.x.repeat(this.options.width / 2); + } +} + +export default VerticalChartFormatter; + + +// width: 20 +// barWidth: 2 +// median: 10 +// padding: 4 \ No newline at end of file diff --git a/ts/char_ts_cii/index.ts b/ts/char_ts_cii/index.ts index 59c3774..ec0cedf 100644 --- a/ts/char_ts_cii/index.ts +++ b/ts/char_ts_cii/index.ts @@ -1,7 +1,8 @@ -import HorizontalChartFormatter from './formatter'; -import ChartProcessor from './processor'; +import HorizontalChartFormatter from './formatters/horizontal'; +import ChartProcessor from './processor/processor'; import defaultOptions from './options'; import { InputData, ChartOptions, ChartData } from './types'; +import VerticalChartFormatter from './formatters/vertical'; class Chartscii { @@ -14,8 +15,8 @@ class Chartscii { const [chart, processedOptions] = processor.process(data); this.chart = chart; - const formatter = new HorizontalChartFormatter(processedOptions); - this.asciiChart = formatter.format(this.chart); + const chartFormatter = config.orientation === 'vertical' ? new VerticalChartFormatter(chart, processedOptions) : new HorizontalChartFormatter(processedOptions) + this.asciiChart = chartFormatter.format(this.chart); } create() { diff --git a/ts/char_ts_cii/options.ts b/ts/char_ts_cii/options.ts index e45173f..8050fbe 100644 --- a/ts/char_ts_cii/options.ts +++ b/ts/char_ts_cii/options.ts @@ -13,6 +13,7 @@ const options: ChartOptions = { width: 50, height: 10, theme: '', + barWidth: 1, max: { label: 0, value: 0, diff --git a/ts/char_ts_cii/processor.ts b/ts/char_ts_cii/processor/processor.ts similarity index 94% rename from ts/char_ts_cii/processor.ts rename to ts/char_ts_cii/processor/processor.ts index 6134031..3fb64c4 100644 --- a/ts/char_ts_cii/processor.ts +++ b/ts/char_ts_cii/processor/processor.ts @@ -1,4 +1,4 @@ -import { ChartDataProcessor, InputData, ChartOptions, ChartData } from './types'; +import { ChartDataProcessor, InputData, ChartOptions, ChartData } from '../types'; class ChartProcessor implements ChartDataProcessor { private options: ChartOptions; @@ -47,7 +47,8 @@ class ChartProcessor implements ChartDataProcessor { } scale(value: number) { - return Math.round((value / this.options.max.value) * this.options.width); + const size = this.options.orientation === 'vertical' ? this.options.height : this.options.width; + return Math.round((value / this.options.max.value) * size); } preprocess(data: InputData[]): { processed: InputData[], key: string, total: number } { diff --git a/ts/char_ts_cii/test.ts b/ts/char_ts_cii/test.ts index 4413741..72fd49d 100644 --- a/ts/char_ts_cii/test.ts +++ b/ts/char_ts_cii/test.ts @@ -13,11 +13,26 @@ const colors = [ const data = []; for (let i = 0; i < colors.length; i++) { const color = colors[i]; - data.push({ value: i + 1, color }); + data.push({ value: i + 1, color, label: `label ${i}` }); } -const chart = new Chartscii(data, { labels: false, width: 100, height: 15 }); +const chart1 = new Chartscii(data, { + labels: false, + width: 100, + height: 10, + barWidth: 1, + // orientation: 'vertical' +}); +console.log(chart1.create()); +const chart2 = new Chartscii(data, { + labels: false, + width: 100, + height: 10, + barWidth: 5, + // fill: '░', + orientation: 'vertical' +}); -console.log(chart.create()); +console.log(chart2.create()); // const data = Array(10).fill(null).map((_, i) => ({ label: `label ${i}`, value: i })) // const chart = new Chartscii(data, diff --git a/ts/char_ts_cii/types.ts b/ts/char_ts_cii/types.ts index 530d4a2..9cbed72 100644 --- a/ts/char_ts_cii/types.ts +++ b/ts/char_ts_cii/types.ts @@ -19,6 +19,7 @@ export type ChartOptions = { width?: number; height?: number; theme?: string; + barWidth?: number; max?: { label: number; value: number; @@ -58,11 +59,13 @@ export interface ChartDataProcessor { sort(data: InputData[]): InputData[]; } -export interface ChartDataFormatter { +export interface HorizontalChartDataFormatter { format(chart: ChartData): string; } - +export interface VerticalChartDataFormatter { + format(...any: any): string; +} From 7f29fd66e70d5a9c094228020e06b82dbd7ea31c Mon Sep 17 00:00:00 2001 From: Tal Hayut Date: Mon, 6 May 2024 17:19:25 +0300 Subject: [PATCH 14/18] fix: oh my god --- ts/char_ts_cii/formatters/vertical.ts | 51 ++++++++++++++++++--------- ts/char_ts_cii/test.ts | 8 +++-- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/ts/char_ts_cii/formatters/vertical.ts b/ts/char_ts_cii/formatters/vertical.ts index 3c83d11..82f3c65 100644 --- a/ts/char_ts_cii/formatters/vertical.ts +++ b/ts/char_ts_cii/formatters/vertical.ts @@ -14,9 +14,7 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { public format(): string { const maxHeight = this.getMaxHeight(); - const barWidth = this.options.barWidth || this.getMaxLabelWidth() || 1; - const verticalSpace = this.options.labels ? 1 : 0; const avg = Math.round(this.options.width / this.chart.length); const median = Math.floor(avg - barWidth); @@ -27,7 +25,7 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { const diff = padding ? (avg - padding - barWidth) : 0; - const verticalChart = this.initializeVerticalChart(maxHeight, padding, verticalSpace); + const verticalChart = this.initializeVerticalChart(maxHeight, padding); this.populateChart(verticalChart, maxHeight, padding + diff, scaledWidth, barWidth); return this.composeFinalChart(verticalChart, barWidth, padding, diff); @@ -60,8 +58,8 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { return 0; } - private initializeVerticalChart(maxHeight: number, padding: number, verticalSpace: number): string[][] { - return Array(maxHeight + verticalSpace).fill('').map(() => Array(this.chart.length).fill('').map(() => ' '.repeat(padding))); + private initializeVerticalChart(maxHeight: number, padding: number): string[][] { + return Array(maxHeight).fill('').map(() => Array(this.chart.length).fill('').map(() => ' '.repeat(padding))); } private populateChart(verticalChart: string[][], maxHeight: number, padding: number, scaledWidth: number, barWidth: number): void { @@ -109,15 +107,32 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { } } - private getLabel(maxLabelWidth: number, padding: number, scaledWidth: number, point: ChartPoint): string { - const label = point.label.padEnd(maxLabelWidth + scaledWidth, ' '); - return ' '.repeat(padding + scaledWidth) + label + ' '.repeat(padding + scaledWidth); + private formatLabel(label: string, color?: string) { + if (this.options.colorLabels) { + const coloredLabel = (color || this.options.color) ? this.colorify(label, color) : label; + return coloredLabel; + } + + return label; + } + + private formatLabels(padding: number, diff: number, barWidth: number) { + const formatted: string[] = []; + const widthDiff = Math.floor((this.options.width) / this.chart.length); + + this.chart.forEach((point, i) => { + const pad = (padding + diff) - point.label.length + (barWidth - 1); + const startPad = '' + formatted.push(' '.repeat(1) + this.formatLabel(point.label, point.color) + ' '.repeat(pad)); + }) + + return formatted.join(''); } private composeFinalChart(verticalChart: string[][], barWidth: number, padding: number, avg: number): string { const chart = verticalChart.map(row => { if (!this.options.naked) { - return this.options.structure.axis + ' ' + row.join('') + return this.options.structure.axis + row.join('') } return row.join('') }) @@ -125,6 +140,7 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { if (!this.options.naked) { chart.unshift(this.makeChartLabel()); chart.push(this.makeVerticalChartBottom(barWidth, padding, avg, verticalChart[verticalChart.length - 1])); + chart.push(this.formatLabels(padding, avg, barWidth)); } return chart.join('\n'); } @@ -134,14 +150,15 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { } private makeVerticalChartBottom(barWidth: number, padding: number, avg: number, lastRow: string[]): string { - return this.options.structure.bottomLeft + this.options.structure.x.repeat(this.options.width / 2); + const width = this.options.width / 2; + const exceeding = barWidth * this.chart.length> this.options.width; + const excess = (barWidth * this.chart.length) - this.options.width; + + const extra = (excess - barWidth) / 2; + + const pad = exceeding ? width + extra + (extra / 2) : width; + return this.options.structure.bottomLeft + this.options.structure.x.repeat(pad + 1); } } -export default VerticalChartFormatter; - - -// width: 20 -// barWidth: 2 -// median: 10 -// padding: 4 \ No newline at end of file +export default VerticalChartFormatter; \ No newline at end of file diff --git a/ts/char_ts_cii/test.ts b/ts/char_ts_cii/test.ts index 72fd49d..d2680d6 100644 --- a/ts/char_ts_cii/test.ts +++ b/ts/char_ts_cii/test.ts @@ -13,9 +13,10 @@ const colors = [ const data = []; for (let i = 0; i < colors.length; i++) { const color = colors[i]; - data.push({ value: i + 1, color, label: `label ${i}` }); + data.push({ value: i + 1, color, label: `label ${i}${i}` }); } const chart1 = new Chartscii(data, { + colorLabels: true, labels: false, width: 100, height: 10, @@ -24,10 +25,11 @@ const chart1 = new Chartscii(data, { }); console.log(chart1.create()); const chart2 = new Chartscii(data, { - labels: false, + colorLabels: true, width: 100, - height: 10, + height: 20, barWidth: 5, + color: 'green', // fill: '░', orientation: 'vertical' }); From d3444b41aa302261ebd926593f1a13be8cb475b7 Mon Sep 17 00:00:00 2001 From: Tal Hayut Date: Mon, 6 May 2024 17:20:35 +0300 Subject: [PATCH 15/18] chore: refactor --- ts/char_ts_cii/formatters/vertical.ts | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/ts/char_ts_cii/formatters/vertical.ts b/ts/char_ts_cii/formatters/vertical.ts index 82f3c65..afc154d 100644 --- a/ts/char_ts_cii/formatters/vertical.ts +++ b/ts/char_ts_cii/formatters/vertical.ts @@ -15,10 +15,7 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { public format(): string { const maxHeight = this.getMaxHeight(); const barWidth = this.options.barWidth || this.getMaxLabelWidth() || 1; - const avg = Math.round(this.options.width / this.chart.length); - const median = Math.floor(avg - barWidth); - const scaledWidth = Math.floor(median / barWidth); const space = Math.round((avg - barWidth) / 2); const padding = space> 0 ? space : 0; @@ -27,7 +24,7 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { const verticalChart = this.initializeVerticalChart(maxHeight, padding); - this.populateChart(verticalChart, maxHeight, padding + diff, scaledWidth, barWidth); + this.populateChart(verticalChart, maxHeight, padding + diff, barWidth); return this.composeFinalChart(verticalChart, barWidth, padding, diff); } @@ -62,7 +59,7 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { return Array(maxHeight).fill('').map(() => Array(this.chart.length).fill('').map(() => ' '.repeat(padding))); } - private populateChart(verticalChart: string[][], maxHeight: number, padding: number, scaledWidth: number, barWidth: number): void { + private populateChart(verticalChart: string[][], maxHeight: number, padding: number, barWidth: number): void { this.chart.forEach((point, index) => { const value = point.scaled; const height = Math.round((value / maxHeight) * maxHeight); @@ -80,11 +77,6 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { verticalChart[i][index] = bars; } } - - // if (this.options.labels) { - // const label = this.getLabel(maxLabelWidth, padding, scaledWidth, point); - // verticalChart[maxHeight][index] = label; - // } }); } @@ -139,7 +131,7 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { if (!this.options.naked) { chart.unshift(this.makeChartLabel()); - chart.push(this.makeVerticalChartBottom(barWidth, padding, avg, verticalChart[verticalChart.length - 1])); + chart.push(this.makeVerticalChartBottom(barWidth)); chart.push(this.formatLabels(padding, avg, barWidth)); } return chart.join('\n'); @@ -149,9 +141,9 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { return this.options.label; } - private makeVerticalChartBottom(barWidth: number, padding: number, avg: number, lastRow: string[]): string { + private makeVerticalChartBottom(barWidth: number): string { const width = this.options.width / 2; - const exceeding = barWidth * this.chart.length> this.options.width; + const exceeding = (barWidth * this.chart.length)> this.options.width; const excess = (barWidth * this.chart.length) - this.options.width; const extra = (excess - barWidth) / 2; From db66aed0b10d8b707b5e733f0f7d084c27120f15 Mon Sep 17 00:00:00 2001 From: Tal Hayut Date: Tue, 7 May 2024 12:18:55 +0300 Subject: [PATCH 16/18] chore: add validator --- ts/char_ts_cii/formatters/horizontal.ts | 8 +- ts/char_ts_cii/formatters/vertical.ts | 73 ++++--- ts/char_ts_cii/index.test.ts | 86 ++++++++ ts/char_ts_cii/options.ts | 4 +- ts/char_ts_cii/processor/processor.ts | 14 +- ts/char_ts_cii/snapshots/index.test.json | 152 +++++++++++++- ts/char_ts_cii/test.ts | 16 +- ts/char_ts_cii/try.ts | 7 + ts/char_ts_cii/types.ts | 1 + ts/char_ts_cii/validator/validator.ts | 25 +++ ts/main.test.ts | 140 ------------- ts/main.ts | 245 ----------------------- ts/tsconfig.json | 20 -- ts/types.ts | 42 ---- ts/utils.ts | 9 - 15 files changed, 338 insertions(+), 504 deletions(-) create mode 100644 ts/char_ts_cii/try.ts create mode 100644 ts/char_ts_cii/validator/validator.ts delete mode 100644 ts/main.test.ts delete mode 100644 ts/main.ts delete mode 100644 ts/tsconfig.json delete mode 100644 ts/types.ts delete mode 100644 ts/utils.ts diff --git a/ts/char_ts_cii/formatters/horizontal.ts b/ts/char_ts_cii/formatters/horizontal.ts index 5d96342..7caec15 100644 --- a/ts/char_ts_cii/formatters/horizontal.ts +++ b/ts/char_ts_cii/formatters/horizontal.ts @@ -71,7 +71,8 @@ class HorizontalChartFormatter implements HorizontalChartDataFormatter { formatLabelSpace(label: string) { if (this.options.max.label) { - const space = this.options.max.label - (label.length); + const addOne = this.options.labels && !this.options.percentage ? 1 : 0; + const space = this.options.max.label - (label.length) + addOne; return this.pad(space) } @@ -127,8 +128,9 @@ class HorizontalChartFormatter implements HorizontalChartDataFormatter { } formatBottom() { - const space = this.pad(this.options.max.label); - return space + this.options.structure.bottomLeft + this.options.structure.x.repeat(this.options.max.scaled / 2); + const addOne = this.options.labels ? 1 : 0; + const space = this.pad(this.options.max.label + addOne); + return space + this.options.structure.bottomLeft + this.options.structure.x.repeat(this.options.max.scaled); } } diff --git a/ts/char_ts_cii/formatters/vertical.ts b/ts/char_ts_cii/formatters/vertical.ts index afc154d..c7d8e60 100644 --- a/ts/char_ts_cii/formatters/vertical.ts +++ b/ts/char_ts_cii/formatters/vertical.ts @@ -1,6 +1,5 @@ import { VerticalChartDataFormatter, ChartOptions, ChartData, ChartPoint } from '../types'; import style from 'styl3'; - class VerticalChartFormatter implements VerticalChartDataFormatter { private chart: ChartPoint[]; private options: ChartOptions; @@ -14,18 +13,18 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { public format(): string { const maxHeight = this.getMaxHeight(); - const barWidth = this.options.barWidth || this.getMaxLabelWidth() || 1; - const avg = Math.round(this.options.width / this.chart.length); + const barWidth = this.options.barWidth || Math.floor(this.options.width / this.chart.length) || 1; - const space = Math.round((avg - barWidth) / 2); - const padding = space> 0 ? space : 0; + const totalBarsWidth = this.chart.length * barWidth; + const diffWidth = this.options.width - totalBarsWidth; + const defaultPadding = Math.round(diffWidth / this.chart.length); - const diff = padding ? (avg - padding - barWidth) : 0; + const padding = this.options.padding || defaultPadding const verticalChart = this.initializeVerticalChart(maxHeight, padding); - this.populateChart(verticalChart, maxHeight, padding + diff, barWidth); - return this.composeFinalChart(verticalChart, barWidth, padding, diff); + this.populateChart(verticalChart, maxHeight, padding, barWidth); + return this.composeFinalChart(verticalChart, barWidth, padding); } colorify(txt: string, color?: string) { @@ -48,8 +47,7 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { private getMaxLabelWidth(): number { if (this.options.labels) { - const labelWidths = this.chart.map(point => point.label.length); - return Math.max(...labelWidths); + return this.options.max.label; } return 0; @@ -71,7 +69,7 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { const fill = this.formatFill(barWidth, padding, color); const fills = this.options.fill ? fill : spaces; - if (i < maxHeight - height) { + if (i + 1 < maxHeight - height) { verticalChart[i][index] = fills; } else { verticalChart[i][index] = bars; @@ -80,6 +78,14 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { }); } + private formatPercentage(point: ChartPoint) { + if (this.options.percentage) { + return `(${point.percentage.toFixed(2)}%)` + } + + return ''; + } + private formatSpace(barWidth: number, padding: number): string { const character = ' '; return character.repeat(barWidth) + ' '.repeat(padding); @@ -99,40 +105,39 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { } } - private formatLabel(label: string, color?: string) { + private formatLabel(point: ChartPoint) { + const label = point.percentage ? `${point.label} ${this.formatPercentage(point)}` : point.label; if (this.options.colorLabels) { - const coloredLabel = (color || this.options.color) ? this.colorify(label, color) : label; + const coloredLabel = (point.color || this.options.color) ? this.colorify(label, point.color) : label; return coloredLabel; } return label; } - private formatLabels(padding: number, diff: number, barWidth: number) { + private formatLabels(verticalChart: string[][], barWidth: number, padding: number) { const formatted: string[] = []; - const widthDiff = Math.floor((this.options.width) / this.chart.length); - this.chart.forEach((point, i) => { - const pad = (padding + diff) - point.label.length + (barWidth - 1); - const startPad = '' - formatted.push(' '.repeat(1) + this.formatLabel(point.label, point.color) + ' '.repeat(pad)); + const pad = Math.abs((padding + barWidth) - point.label.length); + const padStart = i === 0 ? Math.floor(padding / 2) + 1 : 0; + formatted.push(' '.repeat(padStart) + this.formatLabel(point) + ' '.repeat(pad)); }) return formatted.join(''); } - private composeFinalChart(verticalChart: string[][], barWidth: number, padding: number, avg: number): string { + private composeFinalChart(verticalChart: string[][], barWidth: number, padding: number): string { const chart = verticalChart.map(row => { if (!this.options.naked) { - return this.options.structure.axis + row.join('') + return this.options.structure.axis + ' '.repeat(padding / 2) + row.join('') } return row.join('') }) if (!this.options.naked) { chart.unshift(this.makeChartLabel()); - chart.push(this.makeVerticalChartBottom(barWidth)); - chart.push(this.formatLabels(padding, avg, barWidth)); + chart.push(this.makeVerticalChartBottom(verticalChart, barWidth, padding)); + chart.push(this.formatLabels(verticalChart, barWidth, padding)); } return chart.join('\n'); } @@ -141,16 +146,20 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { return this.options.label; } - private makeVerticalChartBottom(barWidth: number): string { - const width = this.options.width / 2; - const exceeding = (barWidth * this.chart.length)> this.options.width; - const excess = (barWidth * this.chart.length) - this.options.width; + private stripAnsi(str: string) { + // const ansiRegex = /[\u001b\u009b][[(][()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=> { }); describe('examples', () => { + it('should match example', async () => { const data = []; for (let i = 0; i < 20; i++) { @@ -79,6 +80,7 @@ describe('examples', () => { const chart = new Chartscii(data, { color: 'pink', colorLabels: true }); await snap(chart.create(), 'chart'); }); + it('should support percentage', async () => { const data = []; for (let i = 0; i < 20; i++) { @@ -122,16 +124,19 @@ describe('examples', () => { const chart = new Chartscii(data, { theme: 'lush', colorLabels: true }); await snap(chart.create(), 'lush theme'); }); + it('should support standard theme', async () => { const data = generateChartData(); const chart = new Chartscii(data, { theme: 'standard', colorLabels: true }); await snap(chart.create(), 'standard theme'); }); + it('should support beach theme', async () => { const data = generateChartData(); const chart = new Chartscii(data, { theme: 'beach', colorLabels: true }); await snap(chart.create(), 'beach theme'); }); + it('should support default theme', async () => { const data = generateChartData(); const chart = new Chartscii(data, { colorLabels: true }); @@ -139,3 +144,84 @@ describe('examples', () => { }); }); + +describe('vertical', () => { + + it('should support vertical orientation', async () => { + const data = []; + for (let i = 0; i < 10; i++) { + data.push({ value: i + 1, label: `label ${i}` }); + } + const chart = new Chartscii(data, { width: 100, color: 'pink', colorLabels: true, orientation: 'vertical' }); + await snap(chart.create(), 'vertical'); + }); + + it('should support barWidth', async () => { + const data = []; + for (let i = 0; i < 10; i++) { + data.push({ value: i + 1, label: `label ${i}` }); + } + const chart = new Chartscii(data, { width: 100, barWidth: 5, color: 'green', colorLabels: true, orientation: 'vertical' }); + await snap(chart.create(), 'barshould support color per bar and label', async () => { + const data = []; + for (let i = 0; i < 10; i++) { + data.push({ value: i + 1, label: `label ${i}`, color: colors[i] }); + } + const chart = new Chartscii(data, { width: 100, barWidth: 5, colorLabels: true, orientation: 'vertical' }); + await snap(chart.create(), 'vertical colors'); + }); + + it('should support labeless vertical chart', async () => { + const data = []; + for (let i = 0; i < 20; i++) { + data.push(i + 1); + } + const chart = new Chartscii(data, { labels: false, orientation: 'vertical' }); + + await snap(chart.create(), 'labeless vertical chart'); + }); + + it('should support labeless colorful chart', async () => { + const data = []; + for (let i = 0; i < colors.length; i++) { + const color = colors[i]; + data.push({ value: i + 1, color }); + } + const chart = new Chartscii(data, { labels: false, orientation: 'vertical' }); + await snap(chart.create(), 'labeless color vertical chart'); + }); + + it('should support pastel theme', async () => { + const data = generateChartData(); + const chart = new Chartscii(data, { theme: 'pastel', barWidth: 2, width: 100, colorLabels: true, orientation: 'vertical' }); + await snap(chart.create(), 'pastel theme vertical'); + }); + + it('should support lush theme', async () => { + const data = generateChartData(); + const chart = new Chartscii(data, { theme: 'lush', barWidth: 2, width: 100, colorLabels: true, orientation: 'vertical' }); + await snap(chart.create(), 'lush theme vertical'); + }); + + it('should support standard theme', async () => { + const data = generateChartData(); + const chart = new Chartscii(data, { theme: 'standard', barWidth: 2, width: 100, colorLabels: true, orientation: 'vertical' }); + await snap(chart.create(), 'standard theme vertical'); + }); + + it('should support beach theme', async () => { + const data = generateChartData(); + const chart = new Chartscii(data, { theme: 'beach', barWidth: 2, width: 100, colorLabels: true, orientation: 'vertical' }); + await snap(chart.create(), 'beach theme vertical'); + }); + + it('should support default theme', async () => { + const data = generateChartData(); + const chart = new Chartscii(data, { barWidth: 2, width: 100, colorLabels: true, orientation: 'vertical' }); + await snap(chart.create(), 'default theme vertical'); + }); +}); + diff --git a/ts/char_ts_cii/options.ts b/ts/char_ts_cii/options.ts index 8050fbe..32d616f 100644 --- a/ts/char_ts_cii/options.ts +++ b/ts/char_ts_cii/options.ts @@ -13,7 +13,7 @@ const options: ChartOptions = { width: 50, height: 10, theme: '', - barWidth: 1, + // barWidth: 1, max: { label: 0, value: 0, @@ -21,7 +21,7 @@ const options: ChartOptions = { }, structure: { y: '╢', - x: '══', + x: '═', bottomLeft: '╚', axis: '║', topLeft: '╔' diff --git a/ts/char_ts_cii/processor/processor.ts b/ts/char_ts_cii/processor/processor.ts index 3fb64c4..edcab9b 100644 --- a/ts/char_ts_cii/processor/processor.ts +++ b/ts/char_ts_cii/processor/processor.ts @@ -1,8 +1,12 @@ import { ChartDataProcessor, InputData, ChartOptions, ChartData } from '../types'; +import ChartValidator from '../validator/validator'; class ChartProcessor implements ChartDataProcessor { private options: ChartOptions; + private validator: ChartValidator; + constructor(options: ChartOptions) { + this.validator = new ChartValidator(options); this.options = options; } @@ -21,13 +25,13 @@ class ChartProcessor implements ChartDataProcessor { const label = typeof p === "number" ? p.toString() : (p.label || p.value.toString()); this.options.max.value = value>= this.options.max.value ? value : this.options.max.value; - + const scaledValue = this.scale(value); this.options.max.scaled = scaledValue>= this.options.max.scaled ? scaledValue : this.options.max.scaled; const percentage = this.percentage(value, total); const percentageLength = percentage ? percentage.toFixed(2).length + 5 : 0; - const potential = this.options.percentage ? label.length + percentageLength : label.length + 1; + const potential = this.options.percentage ? label.length + percentageLength : label.length; if (this.options.labels) { this.options.max.label = potential> this.options.max.label ? potential : this.options.max.label; @@ -59,10 +63,10 @@ class ChartProcessor implements ChartDataProcessor { } process(data: InputData[]): [ChartData, ChartOptions] { - if (!Array.isArray(data)) throw new Error("Input data must be an array"); - if (typeof data[0] === "string") throw new Error("Input values must be numbers"); - const { processed, total } = this.preprocess(data); + + this.validator.validate(data); + const chartData = new Map(); processed.forEach((point, i) => { diff --git a/ts/char_ts_cii/snapshots/index.test.json b/ts/char_ts_cii/snapshots/index.test.json index c1bdacd..dc9deeb 100644 --- a/ts/char_ts_cii/snapshots/index.test.json +++ b/ts/char_ts_cii/snapshots/index.test.json @@ -45,7 +45,7 @@ "\u001b[38;5;219mlabel 17 (8.57%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████████████████████████\u001b[0m", "\u001b[38;5;219mlabel 18 (9.05%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████████████████████████\u001b[0m", "\u001b[38;5;219mlabel 19 (9.52%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████████████████████████\u001b[0m", - " ╚══════════════════════════════════════════════════" + " ╚══════════════════════════════════════════════════" ], "labeless chart": [ "", @@ -142,5 +142,155 @@ "\u001b[96mcyan \u001b[0m╢\u001b[0m\u001b[96m████████████████████████████████████████████\u001b[0m", "\u001b[38;5;215morange \u001b[0m╢\u001b[0m\u001b[38;5;215m██████████████████████████████████████████████████\u001b[0m", " ╚══════════════════════════════════════════════════" + ], + "vertical": [ + "", + "║ \u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m", + "║ \u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m", + "║ \u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m", + "║ \u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m", + "║ \u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m", + "║ \u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m", + "║ \u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m", + "║ \u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m", + "║\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m", + "║\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m\u001b[38;5;219m██████████\u001b[0m", + "╚════════════════════════════════════════════════════════════════════════════════════════════════════", + " \u001b[38;5;219mlabel 0\u001b[0m \u001b[38;5;219mlabel 1\u001b[0m \u001b[38;5;219mlabel 2\u001b[0m \u001b[38;5;219mlabel 3\u001b[0m \u001b[38;5;219mlabel 4\u001b[0m \u001b[38;5;219mlabel 5\u001b[0m \u001b[38;5;219mlabel 6\u001b[0m \u001b[38;5;219mlabel 7\u001b[0m \u001b[38;5;219mlabel 8\u001b[0m \u001b[38;5;219mlabel 9\u001b[0m " + ], + "barWidth": [ + "", + "║ \u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m", + "║ \u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m", + "║ \u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m", + "║ \u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m", + "║ \u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m", + "║ \u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m", + "║ \u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m", + "║ \u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m", + "║ \u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m", + "║ \u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[32m█████ \u001b[0m", + "╚════════════════════════════════════════════════════════════════════════════════════════════════════", + " \u001b[32mlabel 0\u001b[0m \u001b[32mlabel 1\u001b[0m \u001b[32mlabel 2\u001b[0m \u001b[32mlabel 3\u001b[0m \u001b[32mlabel 4\u001b[0m \u001b[32mlabel 5\u001b[0m \u001b[32mlabel 6\u001b[0m \u001b[32mlabel 7\u001b[0m \u001b[32mlabel 8\u001b[0m \u001b[32mlabel 9\u001b[0m " + ], + "vertical colors": [ + "", + "║ █████ █████ ", + "║ \u001b[38;5;215m█████ \u001b[0m█████ █████ ", + "║ \u001b[96m█████ \u001b[0m\u001b[38;5;215m█████ \u001b[0m█████ █████ ", + "║ \u001b[38;5;219m█████ \u001b[0m\u001b[96m█████ \u001b[0m\u001b[38;5;215m█████ \u001b[0m█████ █████ ", + "║ \u001b[35m█████ \u001b[0m\u001b[38;5;219m█████ \u001b[0m\u001b[96m█████ \u001b[0m\u001b[38;5;215m█████ \u001b[0m█████ █████ ", + "║ \u001b[34m█████ \u001b[0m\u001b[35m█████ \u001b[0m\u001b[38;5;219m█████ \u001b[0m\u001b[96m█████ \u001b[0m\u001b[38;5;215m█████ \u001b[0m█████ █████ ", + "║ \u001b[38;5;227m█████ \u001b[0m\u001b[34m█████ \u001b[0m\u001b[35m█████ \u001b[0m\u001b[38;5;219m█████ \u001b[0m\u001b[96m█████ \u001b[0m\u001b[38;5;215m█████ \u001b[0m█████ █████ ", + "║ \u001b[32m█████ \u001b[0m\u001b[38;5;227m█████ \u001b[0m\u001b[34m█████ \u001b[0m\u001b[35m█████ \u001b[0m\u001b[38;5;219m█████ \u001b[0m\u001b[96m█████ \u001b[0m\u001b[38;5;215m█████ \u001b[0m█████ █████ ", + "║ \u001b[38;5;160m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[38;5;227m█████ \u001b[0m\u001b[34m█████ \u001b[0m\u001b[35m█████ \u001b[0m\u001b[38;5;219m█████ \u001b[0m\u001b[96m█████ \u001b[0m\u001b[38;5;215m█████ \u001b[0m█████ █████ ", + "║ \u001b[38;5;160m█████ \u001b[0m\u001b[32m█████ \u001b[0m\u001b[38;5;227m█████ \u001b[0m\u001b[34m█████ \u001b[0m\u001b[35m█████ \u001b[0m\u001b[38;5;219m█████ \u001b[0m\u001b[96m█████ \u001b[0m\u001b[38;5;215m█████ \u001b[0m█████ █████ ", + "╚════════════════════════════════════════════════════════════════════════════════════════════════════", + " \u001b[38;5;160mlabel 0\u001b[0m \u001b[32mlabel 1\u001b[0m \u001b[38;5;227mlabel 2\u001b[0m \u001b[34mlabel 3\u001b[0m \u001b[35mlabel 4\u001b[0m \u001b[38;5;219mlabel 5\u001b[0m \u001b[96mlabel 6\u001b[0m \u001b[38;5;215mlabel 7\u001b[0m label 8 label 9 " + ], + "labeless vertical chart": [ + "", + "║ ██ ██ ██ ██ ", + "║ ██ ██ ██ ██ ██ ██ ", + "║ ██ ██ ██ ██ ██ ██ ██ ██ ", + "║ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ", + "║ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ", + "║ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ", + "║ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ", + "║ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ", + "║██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ", + "║██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ", + "╚════════════════════════════════════════════════════════════", + " 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 " + ], + "labeless color vertical chart": [ + "", + "║ \u001b[96m██████\u001b[0m\u001b[38;5;215m██████\u001b[0m", + "║ \u001b[38;5;219m██████\u001b[0m\u001b[96m██████\u001b[0m\u001b[38;5;215m██████\u001b[0m", + "║ \u001b[38;5;219m██████\u001b[0m\u001b[96m██████\u001b[0m\u001b[38;5;215m██████\u001b[0m", + "║ \u001b[35m██████\u001b[0m\u001b[38;5;219m██████\u001b[0m\u001b[96m██████\u001b[0m\u001b[38;5;215m██████\u001b[0m", + "║ \u001b[34m██████\u001b[0m\u001b[35m██████\u001b[0m\u001b[38;5;219m██████\u001b[0m\u001b[96m██████\u001b[0m\u001b[38;5;215m██████\u001b[0m", + "║ \u001b[38;5;227m██████\u001b[0m\u001b[34m██████\u001b[0m\u001b[35m██████\u001b[0m\u001b[38;5;219m██████\u001b[0m\u001b[96m██████\u001b[0m\u001b[38;5;215m██████\u001b[0m", + "║ \u001b[32m██████\u001b[0m\u001b[38;5;227m██████\u001b[0m\u001b[34m██████\u001b[0m\u001b[35m██████\u001b[0m\u001b[38;5;219m██████\u001b[0m\u001b[96m██████\u001b[0m\u001b[38;5;215m██████\u001b[0m", + "║ \u001b[32m██████\u001b[0m\u001b[38;5;227m██████\u001b[0m\u001b[34m██████\u001b[0m\u001b[35m██████\u001b[0m\u001b[38;5;219m██████\u001b[0m\u001b[96m██████\u001b[0m\u001b[38;5;215m██████\u001b[0m", + "║\u001b[38;5;160m██████\u001b[0m\u001b[32m██████\u001b[0m\u001b[38;5;227m██████\u001b[0m\u001b[34m██████\u001b[0m\u001b[35m██████\u001b[0m\u001b[38;5;219m██████\u001b[0m\u001b[96m██████\u001b[0m\u001b[38;5;215m██████\u001b[0m", + "║\u001b[38;5;160m██████\u001b[0m\u001b[32m██████\u001b[0m\u001b[38;5;227m██████\u001b[0m\u001b[34m██████\u001b[0m\u001b[35m██████\u001b[0m\u001b[38;5;219m██████\u001b[0m\u001b[96m██████\u001b[0m\u001b[38;5;215m██████\u001b[0m", + "╚════════════════════════════════════════════════", + " 1 2 3 4 5 6 7 8 " + ], + "pastel theme vertical": [ + "", + "║ \u001b[38;5;159m██ \u001b[0m\u001b[38;5;209m██ \u001b[0m", + "║ \u001b[38;5;219m██ \u001b[0m\u001b[38;5;159m██ \u001b[0m\u001b[38;5;209m██ \u001b[0m", + "║ \u001b[38;5;219m██ \u001b[0m\u001b[38;5;159m██ \u001b[0m\u001b[38;5;209m██ \u001b[0m", + "║ \u001b[38;5;147m██ \u001b[0m\u001b[38;5;219m██ \u001b[0m\u001b[38;5;159m██ \u001b[0m\u001b[38;5;209m██ \u001b[0m", + "║ \u001b[38;5;39m██ \u001b[0m\u001b[38;5;147m██ \u001b[0m\u001b[38;5;219m██ \u001b[0m\u001b[38;5;159m██ \u001b[0m\u001b[38;5;209m██ \u001b[0m", + "║ \u001b[38;5;228m██ \u001b[0m\u001b[38;5;39m██ \u001b[0m\u001b[38;5;147m██ \u001b[0m\u001b[38;5;219m██ \u001b[0m\u001b[38;5;159m██ \u001b[0m\u001b[38;5;209m██ \u001b[0m", + "║ \u001b[38;5;49m██ \u001b[0m\u001b[38;5;228m██ \u001b[0m\u001b[38;5;39m██ \u001b[0m\u001b[38;5;147m██ \u001b[0m\u001b[38;5;219m██ \u001b[0m\u001b[38;5;159m██ \u001b[0m\u001b[38;5;209m██ \u001b[0m", + "║ \u001b[38;5;49m██ \u001b[0m\u001b[38;5;228m██ \u001b[0m\u001b[38;5;39m██ \u001b[0m\u001b[38;5;147m██ \u001b[0m\u001b[38;5;219m██ \u001b[0m\u001b[38;5;159m██ \u001b[0m\u001b[38;5;209m██ \u001b[0m", + "║ \u001b[31m██ \u001b[0m\u001b[38;5;49m██ \u001b[0m\u001b[38;5;228m██ \u001b[0m\u001b[38;5;39m██ \u001b[0m\u001b[38;5;147m██ \u001b[0m\u001b[38;5;219m██ \u001b[0m\u001b[38;5;159m██ \u001b[0m\u001b[38;5;209m██ \u001b[0m", + "║ \u001b[31m██ \u001b[0m\u001b[38;5;49m██ \u001b[0m\u001b[38;5;228m██ \u001b[0m\u001b[38;5;39m██ \u001b[0m\u001b[38;5;147m██ \u001b[0m\u001b[38;5;219m██ \u001b[0m\u001b[38;5;159m██ \u001b[0m\u001b[38;5;209m██ \u001b[0m", + "╚════════════════════════════════════════════════════════════════════════════════════════════════════════", + " \u001b[31mred\u001b[0m \u001b[38;5;49mgreen\u001b[0m \u001b[38;5;228myellow\u001b[0m \u001b[38;5;39mblue\u001b[0m \u001b[38;5;147mpurple\u001b[0m \u001b[38;5;219mpink\u001b[0m \u001b[38;5;159mcyan\u001b[0m \u001b[38;5;209morange\u001b[0m " + ], + "lush theme vertical": [ + "", + "║ \u001b[38;5;87m██ \u001b[0m\u001b[38;5;202m██ \u001b[0m", + "║ \u001b[38;5;198m██ \u001b[0m\u001b[38;5;87m██ \u001b[0m\u001b[38;5;202m██ \u001b[0m", + "║ \u001b[38;5;198m██ \u001b[0m\u001b[38;5;87m██ \u001b[0m\u001b[38;5;202m██ \u001b[0m", + "║ \u001b[38;5;128m██ \u001b[0m\u001b[38;5;198m██ \u001b[0m\u001b[38;5;87m██ \u001b[0m\u001b[38;5;202m██ \u001b[0m", + "║ \u001b[38;5;57m██ \u001b[0m\u001b[38;5;128m██ \u001b[0m\u001b[38;5;198m██ \u001b[0m\u001b[38;5;87m██ \u001b[0m\u001b[38;5;202m██ \u001b[0m", + "║ \u001b[38;5;226m██ \u001b[0m\u001b[38;5;57m██ \u001b[0m\u001b[38;5;128m██ \u001b[0m\u001b[38;5;198m██ \u001b[0m\u001b[38;5;87m██ \u001b[0m\u001b[38;5;202m██ \u001b[0m", + "║ \u001b[38;5;154m██ \u001b[0m\u001b[38;5;226m██ \u001b[0m\u001b[38;5;57m██ \u001b[0m\u001b[38;5;128m██ \u001b[0m\u001b[38;5;198m██ \u001b[0m\u001b[38;5;87m██ \u001b[0m\u001b[38;5;202m██ \u001b[0m", + "║ \u001b[38;5;154m██ \u001b[0m\u001b[38;5;226m██ \u001b[0m\u001b[38;5;57m██ \u001b[0m\u001b[38;5;128m██ \u001b[0m\u001b[38;5;198m██ \u001b[0m\u001b[38;5;87m██ \u001b[0m\u001b[38;5;202m██ \u001b[0m", + "║ \u001b[38;5;196m██ \u001b[0m\u001b[38;5;154m██ \u001b[0m\u001b[38;5;226m██ \u001b[0m\u001b[38;5;57m██ \u001b[0m\u001b[38;5;128m██ \u001b[0m\u001b[38;5;198m██ \u001b[0m\u001b[38;5;87m██ \u001b[0m\u001b[38;5;202m██ \u001b[0m", + "║ \u001b[38;5;196m██ \u001b[0m\u001b[38;5;154m██ \u001b[0m\u001b[38;5;226m██ \u001b[0m\u001b[38;5;57m██ \u001b[0m\u001b[38;5;128m██ \u001b[0m\u001b[38;5;198m██ \u001b[0m\u001b[38;5;87m██ \u001b[0m\u001b[38;5;202m██ \u001b[0m", + "╚════════════════════════════════════════════════════════════════════════════════════════════════════════", + " \u001b[38;5;196mred\u001b[0m \u001b[38;5;154mgreen\u001b[0m \u001b[38;5;226myellow\u001b[0m \u001b[38;5;57mblue\u001b[0m \u001b[38;5;128mpurple\u001b[0m \u001b[38;5;198mpink\u001b[0m \u001b[38;5;87mcyan\u001b[0m \u001b[38;5;202morange\u001b[0m " + ], + "standard theme vertical": [ + "", + "║ \u001b[38;5;123m██ \u001b[0m\u001b[38;5;214m██ \u001b[0m", + "║ \u001b[38;5;200m██ \u001b[0m\u001b[38;5;123m██ \u001b[0m\u001b[38;5;214m██ \u001b[0m", + "║ \u001b[38;5;200m██ \u001b[0m\u001b[38;5;123m██ \u001b[0m\u001b[38;5;214m██ \u001b[0m", + "║ \u001b[38;5;105m██ \u001b[0m\u001b[38;5;200m██ \u001b[0m\u001b[38;5;123m██ \u001b[0m\u001b[38;5;214m██ \u001b[0m", + "║ \u001b[38;5;27m██ \u001b[0m\u001b[38;5;105m██ \u001b[0m\u001b[38;5;200m██ \u001b[0m\u001b[38;5;123m██ \u001b[0m\u001b[38;5;214m██ \u001b[0m", + "║ \u001b[38;5;11m██ \u001b[0m\u001b[38;5;27m██ \u001b[0m\u001b[38;5;105m██ \u001b[0m\u001b[38;5;200m██ \u001b[0m\u001b[38;5;123m██ \u001b[0m\u001b[38;5;214m██ \u001b[0m", + "║ \u001b[38;5;10m██ \u001b[0m\u001b[38;5;11m██ \u001b[0m\u001b[38;5;27m██ \u001b[0m\u001b[38;5;105m██ \u001b[0m\u001b[38;5;200m██ \u001b[0m\u001b[38;5;123m██ \u001b[0m\u001b[38;5;214m██ \u001b[0m", + "║ \u001b[38;5;10m██ \u001b[0m\u001b[38;5;11m██ \u001b[0m\u001b[38;5;27m██ \u001b[0m\u001b[38;5;105m██ \u001b[0m\u001b[38;5;200m██ \u001b[0m\u001b[38;5;123m██ \u001b[0m\u001b[38;5;214m██ \u001b[0m", + "║ \u001b[38;5;9m██ \u001b[0m\u001b[38;5;10m██ \u001b[0m\u001b[38;5;11m██ \u001b[0m\u001b[38;5;27m██ \u001b[0m\u001b[38;5;105m██ \u001b[0m\u001b[38;5;200m██ \u001b[0m\u001b[38;5;123m██ \u001b[0m\u001b[38;5;214m██ \u001b[0m", + "║ \u001b[38;5;9m██ \u001b[0m\u001b[38;5;10m██ \u001b[0m\u001b[38;5;11m██ \u001b[0m\u001b[38;5;27m██ \u001b[0m\u001b[38;5;105m██ \u001b[0m\u001b[38;5;200m██ \u001b[0m\u001b[38;5;123m██ \u001b[0m\u001b[38;5;214m██ \u001b[0m", + "╚════════════════════════════════════════════════════════════════════════════════════════════════════════", + " \u001b[38;5;9mred\u001b[0m \u001b[38;5;10mgreen\u001b[0m \u001b[38;5;11myellow\u001b[0m \u001b[38;5;27mblue\u001b[0m \u001b[38;5;105mpurple\u001b[0m \u001b[38;5;200mpink\u001b[0m \u001b[38;5;123mcyan\u001b[0m \u001b[38;5;214morange\u001b[0m " + ], + "beach theme vertical": [ + "", + "║ \u001b[38;2;0;255;255m██ \u001b[0m\u001b[38;2;247;126;2m██ \u001b[0m", + "║ \u001b[38;2;222;82;133m██ \u001b[0m\u001b[38;2;0;255;255m██ \u001b[0m\u001b[38;2;247;126;2m██ \u001b[0m", + "║ \u001b[38;2;222;82;133m██ \u001b[0m\u001b[38;2;0;255;255m██ \u001b[0m\u001b[38;2;247;126;2m██ \u001b[0m", + "║ \u001b[38;2;130;119;249m██ \u001b[0m\u001b[38;2;222;82;133m██ \u001b[0m\u001b[38;2;0;255;255m██ \u001b[0m\u001b[38;2;247;126;2m██ \u001b[0m", + "║ \u001b[38;2;146;196;238m██ \u001b[0m\u001b[38;2;130;119;249m██ \u001b[0m\u001b[38;2;222;82;133m██ \u001b[0m\u001b[38;2;0;255;255m██ \u001b[0m\u001b[38;2;247;126;2m██ \u001b[0m", + "║ \u001b[38;2;254;215;102m██ \u001b[0m\u001b[38;2;146;196;238m██ \u001b[0m\u001b[38;2;130;119;249m██ \u001b[0m\u001b[38;2;222;82;133m██ \u001b[0m\u001b[38;2;0;255;255m██ \u001b[0m\u001b[38;2;247;126;2m██ \u001b[0m", + "║ \u001b[38;2;42;183;202m██ \u001b[0m\u001b[38;2;254;215;102m██ \u001b[0m\u001b[38;2;146;196;238m██ \u001b[0m\u001b[38;2;130;119;249m██ \u001b[0m\u001b[38;2;222;82;133m██ \u001b[0m\u001b[38;2;0;255;255m██ \u001b[0m\u001b[38;2;247;126;2m██ \u001b[0m", + "║ \u001b[38;2;42;183;202m██ \u001b[0m\u001b[38;2;254;215;102m██ \u001b[0m\u001b[38;2;146;196;238m██ \u001b[0m\u001b[38;2;130;119;249m██ \u001b[0m\u001b[38;2;222;82;133m██ \u001b[0m\u001b[38;2;0;255;255m██ \u001b[0m\u001b[38;2;247;126;2m██ \u001b[0m", + "║ \u001b[38;2;254;74;73m██ \u001b[0m\u001b[38;2;42;183;202m██ \u001b[0m\u001b[38;2;254;215;102m██ \u001b[0m\u001b[38;2;146;196;238m██ \u001b[0m\u001b[38;2;130;119;249m██ \u001b[0m\u001b[38;2;222;82;133m██ \u001b[0m\u001b[38;2;0;255;255m██ \u001b[0m\u001b[38;2;247;126;2m██ \u001b[0m", + "║ \u001b[38;2;254;74;73m██ \u001b[0m\u001b[38;2;42;183;202m██ \u001b[0m\u001b[38;2;254;215;102m██ \u001b[0m\u001b[38;2;146;196;238m██ \u001b[0m\u001b[38;2;130;119;249m██ \u001b[0m\u001b[38;2;222;82;133m██ \u001b[0m\u001b[38;2;0;255;255m██ \u001b[0m\u001b[38;2;247;126;2m██ \u001b[0m", + "╚════════════════════════════════════════════════════════════════════════════════════════════════════════", + " \u001b[38;2;254;74;73mred\u001b[0m \u001b[38;2;42;183;202mgreen\u001b[0m \u001b[38;2;254;215;102myellow\u001b[0m \u001b[38;2;146;196;238mblue\u001b[0m \u001b[38;2;130;119;249mpurple\u001b[0m \u001b[38;2;222;82;133mpink\u001b[0m \u001b[38;2;0;255;255mcyan\u001b[0m \u001b[38;2;247;126;2morange\u001b[0m " + ], + "default theme vertical": [ + "", + "║ \u001b[96m██ \u001b[0m\u001b[38;5;215m██ \u001b[0m", + "║ \u001b[38;5;219m██ \u001b[0m\u001b[96m██ \u001b[0m\u001b[38;5;215m██ \u001b[0m", + "║ \u001b[38;5;219m██ \u001b[0m\u001b[96m██ \u001b[0m\u001b[38;5;215m██ \u001b[0m", + "║ \u001b[35m██ \u001b[0m\u001b[38;5;219m██ \u001b[0m\u001b[96m██ \u001b[0m\u001b[38;5;215m██ \u001b[0m", + "║ \u001b[34m██ \u001b[0m\u001b[35m██ \u001b[0m\u001b[38;5;219m██ \u001b[0m\u001b[96m██ \u001b[0m\u001b[38;5;215m██ \u001b[0m", + "║ \u001b[38;5;227m██ \u001b[0m\u001b[34m██ \u001b[0m\u001b[35m██ \u001b[0m\u001b[38;5;219m██ \u001b[0m\u001b[96m██ \u001b[0m\u001b[38;5;215m██ \u001b[0m", + "║ \u001b[32m██ \u001b[0m\u001b[38;5;227m██ \u001b[0m\u001b[34m██ \u001b[0m\u001b[35m██ \u001b[0m\u001b[38;5;219m██ \u001b[0m\u001b[96m██ \u001b[0m\u001b[38;5;215m██ \u001b[0m", + "║ \u001b[32m██ \u001b[0m\u001b[38;5;227m██ \u001b[0m\u001b[34m██ \u001b[0m\u001b[35m██ \u001b[0m\u001b[38;5;219m██ \u001b[0m\u001b[96m██ \u001b[0m\u001b[38;5;215m██ \u001b[0m", + "║ \u001b[38;5;160m██ \u001b[0m\u001b[32m██ \u001b[0m\u001b[38;5;227m██ \u001b[0m\u001b[34m██ \u001b[0m\u001b[35m██ \u001b[0m\u001b[38;5;219m██ \u001b[0m\u001b[96m██ \u001b[0m\u001b[38;5;215m██ \u001b[0m", + "║ \u001b[38;5;160m██ \u001b[0m\u001b[32m██ \u001b[0m\u001b[38;5;227m██ \u001b[0m\u001b[34m██ \u001b[0m\u001b[35m██ \u001b[0m\u001b[38;5;219m██ \u001b[0m\u001b[96m██ \u001b[0m\u001b[38;5;215m██ \u001b[0m", + "╚════════════════════════════════════════════════════════════════════════════════════════════════════════", + " \u001b[38;5;160mred\u001b[0m \u001b[32mgreen\u001b[0m \u001b[38;5;227myellow\u001b[0m \u001b[34mblue\u001b[0m \u001b[35mpurple\u001b[0m \u001b[38;5;219mpink\u001b[0m \u001b[96mcyan\u001b[0m \u001b[38;5;215morange\u001b[0m " ] } \ No newline at end of file diff --git a/ts/char_ts_cii/test.ts b/ts/char_ts_cii/test.ts index d2680d6..9db62da 100644 --- a/ts/char_ts_cii/test.ts +++ b/ts/char_ts_cii/test.ts @@ -8,28 +8,34 @@ const colors = [ 'pink', 'cyan', 'orange', + 'purple', + 'pink', ]; const data = []; for (let i = 0; i < colors.length; i++) { const color = colors[i]; - data.push({ value: i + 1, color, label: `label ${i}${i}` }); + data.push({ value: i + 1, color, label: color }); } const chart1 = new Chartscii(data, { colorLabels: true, labels: false, width: 100, height: 10, - barWidth: 1, + // barWidth: 1, + // width: process.stdout.columns - 1, // orientation: 'vertical' }); console.log(chart1.create()); + const chart2 = new Chartscii(data, { colorLabels: true, - width: 100, - height: 20, - barWidth: 5, + // width: 100, + // height: 20, + // barWidth: 2, + // padding: 2, color: 'green', + // percentage: true, // fill: '░', orientation: 'vertical' }); diff --git a/ts/char_ts_cii/try.ts b/ts/char_ts_cii/try.ts new file mode 100644 index 0000000..b27a3f6 --- /dev/null +++ b/ts/char_ts_cii/try.ts @@ -0,0 +1,7 @@ +import Chartscii from '.'; +const data = []; +for (let i = 0; i < 20; i++) { + data.push(i + 1); +} +const chart = new Chartscii(data, { labels: false, orientation: 'vertical' }); +console.log(chart.create()); \ No newline at end of file diff --git a/ts/char_ts_cii/types.ts b/ts/char_ts_cii/types.ts index 9cbed72..1a5c21d 100644 --- a/ts/char_ts_cii/types.ts +++ b/ts/char_ts_cii/types.ts @@ -20,6 +20,7 @@ export type ChartOptions = { height?: number; theme?: string; barWidth?: number; + padding?: number; max?: { label: number; value: number; diff --git a/ts/char_ts_cii/validator/validator.ts b/ts/char_ts_cii/validator/validator.ts new file mode 100644 index 0000000..ca20edd --- /dev/null +++ b/ts/char_ts_cii/validator/validator.ts @@ -0,0 +1,25 @@ +import { ChartData, ChartOptions, InputData } from '../types'; + +class ChartValidator { + private options: ChartOptions; + + constructor(options: ChartOptions) { + this.options = options; + } + + error(text: string) { + return new Error(text); + } + + + validate(data: InputData[]) { + if (!Array.isArray(data)) throw new Error("Input data must be an array"); + if (typeof data[0] === "string") throw new Error("Input values must be numbers. e.g [1, 2, 3] or [{value: 1}, {value: 2}]"); + + if (!data.length) throw new Error('No data provided'); + + } + +} + +export default ChartValidator; \ No newline at end of file diff --git a/ts/main.test.ts b/ts/main.test.ts deleted file mode 100644 index bbdb729..0000000 --- a/ts/main.test.ts +++ /dev/null @@ -1,140 +0,0 @@ -import chai from 'chai'; -const expect = chai.expect; -import Chartscii from './main'; -import snap from 'snaptdout'; -const colors = [ - 'red', - 'green', - 'yellow', - 'blue', - 'purple', - 'pink', - 'cyan', - 'orange', -]; - -function generateChartData() { - const data = []; - for (let i = 0; i < colors.length; i++) { - const color = colors[i]; - data.push({ value: i + 1, label: color, color }); - } - return data; -} - -describe('chartscii tests', () => { - let data, chart: any; - - beforeEach(() => { - data = [...Array(10).keys()]; - chart = new Chartscii(data); - }); - - it('should initialize chart array with all values', () => { - const result = chart.get(); - expect(result.length).to.equal(10); - }); - - it('should support 0 values', () => { - const result = chart.get(); - expect(result[0]).to.include({ value: '0' }); - }); - - it('should support { value }', () => { - const data = [...Array(10).keys()].map((key) => { - return { value: key }; - }); - chart = new Chartscii(data); - const result = chart.get()[0]; - expect(result.value).to.equal('0'); - }); - - it('should support { value, label }', () => { - let counter = 0; - const data = [...Array(10).keys()].map((key) => { - return { value: key, label: `label ${counter++}` }; - }); - chart = new Chartscii(data); - const result = chart.get()[0]; - expect(result.label).to.equal('label 0'); - }); - - it('should support percentage', () => { - let counter = 0; - const data = [...Array(10).keys()].map((key) => { - return { value: key, label: `label ${counter++}` }; - }); - chart = new Chartscii(data, { percentage: true }); - const result = chart.get()[0]; - expect(result.label).to.include('%'); - }); -}); - -describe('examples', () => { - it('should match example', async () => { - const data = []; - for (let i = 0; i < 20; i++) { - data.push({ value: i, label: `label ${i}` }); - } - const chart = new Chartscii(data, { color: 'pink', colorLabels: true }); - await snap(chart.create(), 'chart'); - }); - it('should support percentage', async () => { - const data = []; - for (let i = 0; i < 20; i++) { - data.push({ value: i + 1, label: `label ${i}` }); - } - const chart = new Chartscii(data, { - color: 'pink', - colorLabels: true, - percentage: true, - }); - await snap(chart.create(), 'percentage'); - }); - - it('should support labeless chart', async () => { - const data = []; - for (let i = 0; i < 20; i++) { - data.push(i + 1); - } - const chart = new Chartscii(data, { labels: false }); - await snap(chart.create(), 'labeless chart'); - }); - - it('should support labeless colorful chart', async () => { - const data = []; - for (let i = 0; i < colors.length; i++) { - const color = colors[i]; - data.push({ value: i + 1, color }); - } - const chart = new Chartscii(data, { labels: false }); - await snap(chart.create(), 'labeless color chart'); - }); - - it('should support pastel theme', async () => { - const data = generateChartData(); - const chart = new Chartscii(data, { theme: 'pastel', colorLabels: true }); - await snap(chart.create(), 'pastel theme'); - }); - it('should support lush theme', async () => { - const data = generateChartData(); - const chart = new Chartscii(data, { theme: 'lush', colorLabels: true }); - await snap(chart.create(), 'lush theme'); - }); - it('should support standard theme', async () => { - const data = generateChartData(); - const chart = new Chartscii(data, { theme: 'standard', colorLabels: true }); - await snap(chart.create(), 'standard theme'); - }); - it('should support beach theme', async () => { - const data = generateChartData(); - const chart = new Chartscii(data, { theme: 'beach', colorLabels: true }); - await snap(chart.create(), 'beach theme'); - }); - it('should support default theme', async () => { - const data = generateChartData(); - const chart = new Chartscii(data, { colorLabels: true }); - await snap(chart.create(), 'default theme'); - }); - -}); diff --git a/ts/main.ts b/ts/main.ts deleted file mode 100644 index 18b907d..0000000 --- a/ts/main.ts +++ /dev/null @@ -1,245 +0,0 @@ -import style from 'styl3'; -import defaultOptions from '../config/config'; -import { ChartData, ChartOptions, ChartPoint, Measures, Point } from './types'; -import { getPointValue } from '../utils'; - -class Chartscii { - private chart: ChartPoint[]; - private measures: Measures; - private options: ChartOptions; - private colors: Record; - private width: number; - private data: ChartData; - - constructor(data: ChartData, options?: ChartOptions) { - this.chart = []; - this.measures = { numeric: 0, count: 0, label: 0, space: 1 } - this.options = this.setOptions(options); - this.colors = style({ theme: this.options.theme }); - this.width = this.options.width; - this.data = this.sortData(data, this.options.reverse); - this.createGraphAxis(); - } - - setOptions(options: ChartOptions = {}) { - const newOptions = { ...defaultOptions, ...options }; - return newOptions; - } - - sortData(data: ChartData, reverse?: boolean) { - if (this.options.sort) { - data = this.sortSmallToLarge(data); - } - if (reverse) { - data = data.reverse(); - } - return data; - } - - getTotal(data: ChartData): number { - return data.reduce((a, p) => a += getPointValue(p), 0); - } - - getPercentageData(value: number, label?: string) { - const total = this.getTotal(this.data); - const avg = value / total; - const percentage = `${(avg * 100).toFixed(1)}%`; - return `${label || value} (${percentage})`; - } - - colorLabel(label: string, color: string) { - return label.toString().replace(label, this.colorify(label, color)); - } - - updateMaxLabelLength(label: string) { - return label.length>= this.measures.label - ? label.length - : this.measures.label; - } - - updateMaxNumeric(value: number) { - return value>= this.measures.numeric ? value : this.measures.numeric; - } - - colorify(txt: string, color: string) { - if (color) { - if (color.includes('#')) { - return this.colors.hex(color)`${txt}`; - } else if (color.match(/[0-9]/)) { - return this.colors.ansi(color)`${txt}`; - } else if (Array.isArray(color)) { - return this.colors.rgb(...color)`${txt}`; - } else { - return this.colors[color]`${txt}`; - } - } - } - - createGraphAxis() { - this.measures.space = this.measures.label || 1; - - const lines = this.data.map((point) => this.line(point)); - - for (const point of lines) { - const value = getPointValue(point); - const color = point.color || this.options.color; - - if (!point.label) { - const key = this.formatLabelessLine(point, value); - this.chart.push({ key, value, color }); - } else { - const key = this.formatLabelLine(point); - this.chart.push({ key, ...point, value }); - } - } - - return this.chart; - } - - formatLabelessLine(point: any, value: any) { - const space = this.measures.label - point.labelColorLess; - if (this.options.labels !== false) { - return this.formatLine(space, value); - } - - return this.options.naked - ? `${' '.repeat(space + value.length)}` - : `${' '.repeat(space + value.length)} ${this.options.structure.noLabelChar - }`; - } - - formatLabelLine(point: any) { - const space = this.measures.label - (point.labelColorLess || point.label.length); - return this.formatLine(space, point.label); - } - - formatLine(space: any, value: any) { - return this.options.naked - ? `${' '.repeat(space)}${value} ` - : `${' '.repeat(space)}${value} ${this.options.structure.y}`; - } - - line(point: Point | number) { - const label = point.label; - const rawValue = getPointValue(point); - const value = rawValue === 0 ? rawValue.toString() : rawValue - - this.measures.numeric = this.updateMaxNumeric(rawValue); - - if (label) { - return this.makeLabelPoint(point) - } - - return this.makeValuePoint({ ...point, value }); - - } - - makeLabelPoint(point: Point & {labelColorLess: number}) { - const value = typeof point === 'object' ? point.value : point; - const color = point.color || this.options.color; - const label = point.label; - - this.measures.label = this.updateMaxLabelLength(point.label); - point.labelColorLess = point.label.length; - - if (this.options.percentage) { - point.label = this.getPercentageData(value, label); - point.labelColorLess = point.label.length; - this.measures.label = this.updateMaxLabelLength(point.label); - } - - if (this.options.colorLabels) { - point.label = this.colorLabel(point.label, color); - } - - return point; - } - - makeValuePoint(point: any) { - const color = point.color || this.options.color; - const value = getPointValue(point); - - let labelColorLess = value.toString().length; - this.measures.label = this.updateMaxLabelLength(value.toString()); - - if (this.options.percentage) { - point.label = this.getPercentageData(value); - this.measures.label = this.updateMaxLabelLength(point.label); - labelColorLess = point.label.length; - } - - if (this.options.colorLabels) { - const printValue = point.label || value; - point.label = this.colorLabel(printValue, color); - } - - return { value, label: point.label, labelColorLess, color }; - } - - sortSmallToLarge(arr: any) { - const sorted = arr.sort((a: any, b: any) => { - if (a.label && this.options.sort) { - return a.label.toLowerCase().localeCompare(b.label.toLowerCase()); - } - if (a.value) { - return a.value - b.value; - } - return a - b; - }); - - return sorted; - } - - makeChartLabel() { - if (this.options.label) { - const space = ' '.repeat(this.measures.space + 1); - return this.options.color - ? `${this.colorify(this.options.label, this.options.color)}${this.colors.colors.reset}${space}` - : `${this.options.label}${space}`; - } - - return ''; - } - - makeChartBottom() { - const base = this.options.labels - ? ' '.repeat(this.measures.label + 1) + this.options.structure.leftCorner - : ' '.repeat(this.measures.label> 1 ? this.measures.label - 1 : this.measures.label) + this.options.structure.leftCorner; - - return base + this.options.structure.x.repeat((this.width / 2)) - } - - create() { - const asciiChart = []; - - for (const point of this.chart) { - const color = point.color || this.options.color; - const scaledValue = this.getScaledValue(point.value); - const fill = this.options.fill ? this.options.fill.repeat(this.width - scaledValue) : ''; - const line = color - ? `${point.key}${this.colorify(`${this.options.char.repeat(scaledValue)}${fill}`, color)}` - : `${point.key}${this.options.char.repeat(scaledValue)}${fill}` - - asciiChart.push(line); - } - - if (this.options.label) { - asciiChart.push(this.makeChartLabel()); - } - - asciiChart.push(this.makeChartBottom()) - return asciiChart.join('\n'); - } - - - - getScaledValue(value: any) { - return Math.round((value / this.measures.numeric) * this.width); - } - - get() { - return this.chart; - } -} - -export default Chartscii; diff --git a/ts/tsconfig.json b/ts/tsconfig.json deleted file mode 100644 index 94b20bf..0000000 --- a/ts/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "target": "es2020", // Compile to ECMAScript 2020. Supports modern JS features. - "module": "commonjs", // Use CommonJS module system, suitable for Node.js. - "lib": ["es2020", "dom"], // Include typings for ES2020 and DOM (optional, remove if not manipulating DOM). - "outDir": "./dist", // Output directory for compiled files. - "rootDir": ".", // Root directory of source files. - "strict": false, // Enable all strict type-checking options. - "esModuleInterop": true, // Enables emit interoperability between CommonJS and ES Modules. - "moduleResolution": "node", // Resolve modules using Node.js's module resolution strategy. - "allowJs": true, // Allow JavaScript files to be compiled. - "noImplicitAny": true, // Raise error on expressions and declarations with an implied 'any' type. - "noImplicitReturns": true, // Report error when not all code paths in function return a value. - "noUnusedLocals": true, // Report errors on unused local variables. - "noUnusedParameters": true, // Report errors on unused parameters. - "removeComments": true, // Do not emit comments to output. - "sourceMap": true, // Generates corresponding '.map' file. - "types": ["@types/mocha", "@types/node"] - }, -} diff --git a/ts/types.ts b/ts/types.ts deleted file mode 100644 index 9d41e36..0000000 --- a/ts/types.ts +++ /dev/null @@ -1,42 +0,0 @@ -export type ChartPoint = { - key: string; - value: number | string; - color?: string; - label?: string; -} - -export type Measures = { - numeric: number; - count: number; - label: number; - space: number; -} - -export type ChartOptions = { - sort?: boolean; - percentage?: boolean; - colorLabels?: boolean; - reverse?: boolean; - naked?: boolean; - labels?: boolean; - color?: string; - label?: string; - char?: string; - fill?: string; - width?: number; - theme?: string; - structure?: { - y: string; - x: string; - leftCorner: string; - noLabelChar: string; - }, -} - -export type Point = { - value: number; - color?: string; - label?: string; -} - -export type ChartData = Point[] | number[]; \ No newline at end of file diff --git a/ts/utils.ts b/ts/utils.ts deleted file mode 100644 index 85329f5..0000000 --- a/ts/utils.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Point } from './types'; - -export function getPointValue(point: Point | number): number { - return typeof point === "number" ? point : point.value; -} - -export function getPointLabel(point: Point | number): string { - return typeof point === "number" ? point.toString() : point.label; -} \ No newline at end of file From 40c5eccfd1176003aae6e93cd8ab437a5b9149d7 Mon Sep 17 00:00:00 2001 From: Tal Hayut Date: Tue, 7 May 2024 16:28:29 +0300 Subject: [PATCH 17/18] chore: align labels --- snapshots/main.test.json | 137 ------------ ts/char_ts_cii/formatters/vertical.ts | 7 +- ts/char_ts_cii/options.ts | 2 +- ts/char_ts_cii/snapshots/index.test.json | 262 +++++++++++------------ ts/char_ts_cii/test.ts | 4 +- 5 files changed, 138 insertions(+), 274 deletions(-) delete mode 100644 snapshots/main.test.json diff --git a/snapshots/main.test.json b/snapshots/main.test.json deleted file mode 100644 index 4c07366..0000000 --- a/snapshots/main.test.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "chart": [ - " \u001b[38;5;219mlabel 0\u001b[0m ╢\u001b[38;5;219m\u001b[0m", - " \u001b[38;5;219mlabel 1\u001b[0m ╢\u001b[38;5;219m█████\u001b[0m", - " \u001b[38;5;219mlabel 2\u001b[0m ╢\u001b[38;5;219m███████████\u001b[0m", - " \u001b[38;5;219mlabel 3\u001b[0m ╢\u001b[38;5;219m████████████████\u001b[0m", - " \u001b[38;5;219mlabel 4\u001b[0m ╢\u001b[38;5;219m█████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 5\u001b[0m ╢\u001b[38;5;219m██████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 6\u001b[0m ╢\u001b[38;5;219m████████████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 7\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 8\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 9\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 10\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 11\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 12\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 13\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 14\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 15\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 16\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 17\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 18\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 19\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" - ], - "percentage": [ - " \u001b[38;5;219mlabel 0 (0.5%)\u001b[0m ╢\u001b[38;5;219m█████\u001b[0m", - " \u001b[38;5;219mlabel 1 (1.0%)\u001b[0m ╢\u001b[38;5;219m██████████\u001b[0m", - " \u001b[38;5;219mlabel 2 (1.4%)\u001b[0m ╢\u001b[38;5;219m███████████████\u001b[0m", - " \u001b[38;5;219mlabel 3 (1.9%)\u001b[0m ╢\u001b[38;5;219m████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 4 (2.4%)\u001b[0m ╢\u001b[38;5;219m█████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 5 (2.9%)\u001b[0m ╢\u001b[38;5;219m██████████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 6 (3.3%)\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 7 (3.8%)\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 8 (4.3%)\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;219mlabel 9 (4.8%)\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 10 (5.2%)\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 11 (5.7%)\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 12 (6.2%)\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 13 (6.7%)\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 14 (7.1%)\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 15 (7.6%)\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 16 (8.1%)\u001b[0m ╢\u001b[38;5;219m█████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 17 (8.6%)\u001b[0m ╢\u001b[38;5;219m██████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 18 (9.0%)\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 19 (9.5%)\u001b[0m ╢\u001b[38;5;219m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" - ], - "labeless chart": [ - " ║█████", - " ║██████████", - " ║███████████████", - " ║████████████████████", - " ║█████████████████████████", - " ║██████████████████████████████", - " ║███████████████████████████████████", - " ║████████████████████████████████████████", - " ║█████████████████████████████████████████████", - " ║██████████████████████████████████████████████████", - " ║███████████████████████████████████████████████████████", - " ║████████████████████████████████████████████████████████████", - " ║█████████████████████████████████████████████████████████████████", - " ║██████████████████████████████████████████████████████████████████████", - " ║███████████████████████████████████████████████████████████████████████████", - " ║████████████████████████████████████████████████████████████████████████████████", - " ║█████████████████████████████████████████████████████████████████████████████████████", - " ║██████████████████████████████████████████████████████████████████████████████████████████", - " ║███████████████████████████████████████████████████████████████████████████████████████████████", - " ║████████████████████████████████████████████████████████████████████████████████████████████████████", - " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" - ], - "labeless color chart": [ - " ║\u001b[38;5;160m█████████████\u001b[0m", - " ║\u001b[32m█████████████████████████\u001b[0m", - " ║\u001b[38;5;227m██████████████████████████████████████\u001b[0m", - " ║\u001b[34m██████████████████████████████████████████████████\u001b[0m", - " ║\u001b[35m███████████████████████████████████████████████████████████████\u001b[0m", - " ║\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", - " ║\u001b[96m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " ║\u001b[38;5;215m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" - ], - "pastel theme": [ - " \u001b[31mred\u001b[0m ╢\u001b[31m█████████████\u001b[0m", - " \u001b[38;5;49mgreen\u001b[0m ╢\u001b[38;5;49m█████████████████████████\u001b[0m", - "\u001b[38;5;228myellow\u001b[0m ╢\u001b[38;5;228m██████████████████████████████████████\u001b[0m", - " \u001b[38;5;39mblue\u001b[0m ╢\u001b[38;5;39m██████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;147mpurple\u001b[0m ╢\u001b[38;5;147m███████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;219mpink\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;159mcyan\u001b[0m ╢\u001b[38;5;159m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;209morange\u001b[0m ╢\u001b[38;5;209m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" - ], - "lush theme": [ - " \u001b[38;5;196mred\u001b[0m ╢\u001b[38;5;196m█████████████\u001b[0m", - " \u001b[38;5;154mgreen\u001b[0m ╢\u001b[38;5;154m█████████████████████████\u001b[0m", - "\u001b[38;5;226myellow\u001b[0m ╢\u001b[38;5;226m██████████████████████████████████████\u001b[0m", - " \u001b[38;5;57mblue\u001b[0m ╢\u001b[38;5;57m██████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;128mpurple\u001b[0m ╢\u001b[38;5;128m███████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;198mpink\u001b[0m ╢\u001b[38;5;198m███████████████████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;87mcyan\u001b[0m ╢\u001b[38;5;87m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;202morange\u001b[0m ╢\u001b[38;5;202m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" - ], - "standard theme": [ - " \u001b[38;5;9mred\u001b[0m ╢\u001b[38;5;9m█████████████\u001b[0m", - " \u001b[38;5;10mgreen\u001b[0m ╢\u001b[38;5;10m█████████████████████████\u001b[0m", - "\u001b[38;5;11myellow\u001b[0m ╢\u001b[38;5;11m██████████████████████████████████████\u001b[0m", - " \u001b[38;5;27mblue\u001b[0m ╢\u001b[38;5;27m██████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;105mpurple\u001b[0m ╢\u001b[38;5;105m███████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;200mpink\u001b[0m ╢\u001b[38;5;200m███████████████████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;123mcyan\u001b[0m ╢\u001b[38;5;123m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;214morange\u001b[0m ╢\u001b[38;5;214m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" - ], - "beach theme": [ - " \u001b[38;2;254;74;73mred\u001b[0m ╢\u001b[38;2;254;74;73m█████████████\u001b[0m", - " \u001b[38;2;42;183;202mgreen\u001b[0m ╢\u001b[38;2;42;183;202m█████████████████████████\u001b[0m", - "\u001b[38;2;254;215;102myellow\u001b[0m ╢\u001b[38;2;254;215;102m██████████████████████████████████████\u001b[0m", - " \u001b[38;2;146;196;238mblue\u001b[0m ╢\u001b[38;2;146;196;238m██████████████████████████████████████████████████\u001b[0m", - "\u001b[38;2;130;119;249mpurple\u001b[0m ╢\u001b[38;2;130;119;249m███████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;2;222;82;133mpink\u001b[0m ╢\u001b[38;2;222;82;133m███████████████████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;2;0;255;255mcyan\u001b[0m ╢\u001b[38;2;0;255;255m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;2;247;126;2morange\u001b[0m ╢\u001b[38;2;247;126;2m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" - ], - "default theme": [ - " \u001b[38;5;160mred\u001b[0m ╢\u001b[38;5;160m█████████████\u001b[0m", - " \u001b[32mgreen\u001b[0m ╢\u001b[32m█████████████████████████\u001b[0m", - "\u001b[38;5;227myellow\u001b[0m ╢\u001b[38;5;227m██████████████████████████████████████\u001b[0m", - " \u001b[34mblue\u001b[0m ╢\u001b[34m██████████████████████████████████████████████████\u001b[0m", - "\u001b[35mpurple\u001b[0m ╢\u001b[35m███████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[38;5;219mpink\u001b[0m ╢\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", - " \u001b[96mcyan\u001b[0m ╢\u001b[96m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;215morange\u001b[0m ╢\u001b[38;5;215m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", - " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" - ] -} \ No newline at end of file diff --git a/ts/char_ts_cii/formatters/vertical.ts b/ts/char_ts_cii/formatters/vertical.ts index c7d8e60..1db0847 100644 --- a/ts/char_ts_cii/formatters/vertical.ts +++ b/ts/char_ts_cii/formatters/vertical.ts @@ -118,9 +118,10 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { private formatLabels(verticalChart: string[][], barWidth: number, padding: number) { const formatted: string[] = []; this.chart.forEach((point, i) => { - const pad = Math.abs((padding + barWidth) - point.label.length); - const padStart = i === 0 ? Math.floor(padding / 2) + 1 : 0; - formatted.push(' '.repeat(padStart) + this.formatLabel(point) + ' '.repeat(pad)); + const diff = barWidth> point.label.length ? barWidth - point.label.length : point.label.length - barWidth; + const padLeft = i === 0 ? Math.floor(padding / 2) + 1 : 0; + const padRight = Math.abs((padding +barWidth) - point.label.length); + formatted.push(' '.repeat(padLeft) + this.formatLabel(point) + ' '.repeat(padRight)); }) return formatted.join(''); diff --git a/ts/char_ts_cii/options.ts b/ts/char_ts_cii/options.ts index 32d616f..0ea1245 100644 --- a/ts/char_ts_cii/options.ts +++ b/ts/char_ts_cii/options.ts @@ -10,7 +10,7 @@ const options: ChartOptions = { labels: true, char: '█', naked: false, - width: 50, + width: 100, height: 10, theme: '', // barWidth: 1, diff --git a/ts/char_ts_cii/snapshots/index.test.json b/ts/char_ts_cii/snapshots/index.test.json index dc9deeb..b805ed5 100644 --- a/ts/char_ts_cii/snapshots/index.test.json +++ b/ts/char_ts_cii/snapshots/index.test.json @@ -1,147 +1,147 @@ { "chart": [ "\u001b[38;5;219m\u001b[0m", - "\u001b[38;5;219mlabel 0 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███\u001b[0m", - "\u001b[38;5;219mlabel 1 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████\u001b[0m", - "\u001b[38;5;219mlabel 2 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████\u001b[0m", - "\u001b[38;5;219mlabel 3 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████\u001b[0m", - "\u001b[38;5;219mlabel 4 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████\u001b[0m", - "\u001b[38;5;219mlabel 5 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████\u001b[0m", - "\u001b[38;5;219mlabel 6 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████\u001b[0m", - "\u001b[38;5;219mlabel 7 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 8 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 9 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 10 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 11 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 12 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 13 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 14 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 15 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 16 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 17 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 18 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 19 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████████████████████████\u001b[0m", - " ╚══════════════════════════════════════════════════" + "\u001b[38;5;219mlabel 0 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████\u001b[0m", + "\u001b[38;5;219mlabel 1 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████\u001b[0m", + "\u001b[38;5;219mlabel 2 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████\u001b[0m", + "\u001b[38;5;219mlabel 3 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 4 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 5 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 6 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 7 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 8 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 9 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 10 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 11 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 12 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 13 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 14 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 15 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 16 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 17 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 18 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 19 \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" ], "percentage": [ "\u001b[38;5;219m\u001b[0m", - "\u001b[38;5;219mlabel 0 (0.48%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███\u001b[0m", - "\u001b[38;5;219mlabel 1 (0.95%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████\u001b[0m", - "\u001b[38;5;219mlabel 2 (1.43%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████\u001b[0m", - "\u001b[38;5;219mlabel 3 (1.90%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████\u001b[0m", - "\u001b[38;5;219mlabel 4 (2.38%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████\u001b[0m", - "\u001b[38;5;219mlabel 5 (2.86%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████\u001b[0m", - "\u001b[38;5;219mlabel 6 (3.33%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████\u001b[0m", - "\u001b[38;5;219mlabel 7 (3.81%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 8 (4.29%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 9 (4.76%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 10 (5.24%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 11 (5.71%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 12 (6.19%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 13 (6.67%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 14 (7.14%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 15 (7.62%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 16 (8.10%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 17 (8.57%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 18 (9.05%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;219mlabel 19 (9.52%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████████████████████████\u001b[0m", - " ╚══════════════════════════════════════════════════" + "\u001b[38;5;219mlabel 0 (0.48%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████\u001b[0m", + "\u001b[38;5;219mlabel 1 (0.95%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████\u001b[0m", + "\u001b[38;5;219mlabel 2 (1.43%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████\u001b[0m", + "\u001b[38;5;219mlabel 3 (1.90%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 4 (2.38%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 5 (2.86%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 6 (3.33%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 7 (3.81%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 8 (4.29%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 9 (4.76%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 10 (5.24%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 11 (5.71%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 12 (6.19%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 13 (6.67%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 14 (7.14%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 15 (7.62%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 16 (8.10%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m█████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 17 (8.57%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m██████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 18 (9.05%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mlabel 19 (9.52%) \u001b[0m╢\u001b[38;5;219m\u001b[0m\u001b[38;5;219m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" ], "labeless chart": [ "", - "\u001b[0m║███", "\u001b[0m║█████", - "\u001b[0m║████████", "\u001b[0m║██████████", - "\u001b[0m║█████████████", "\u001b[0m║███████████████", - "\u001b[0m║██████████████████", "\u001b[0m║████████████████████", - "\u001b[0m║███████████████████████", "\u001b[0m║█████████████████████████", - "\u001b[0m║████████████████████████████", "\u001b[0m║██████████████████████████████", - "\u001b[0m║█████████████████████████████████", "\u001b[0m║███████████████████████████████████", - "\u001b[0m║██████████████████████████████████████", "\u001b[0m║████████████████████████████████████████", - "\u001b[0m║███████████████████████████████████████████", "\u001b[0m║█████████████████████████████████████████████", - "\u001b[0m║████████████████████████████████████████████████", "\u001b[0m║██████████████████████████████████████████████████", - "╚══════════════════════════════════════════════════" + "\u001b[0m║███████████████████████████████████████████████████████", + "\u001b[0m║████████████████████████████████████████████████████████████", + "\u001b[0m║█████████████████████████████████████████████████████████████████", + "\u001b[0m║██████████████████████████████████████████████████████████████████████", + "\u001b[0m║███████████████████████████████████████████████████████████████████████████", + "\u001b[0m║████████████████████████████████████████████████████████████████████████████████", + "\u001b[0m║█████████████████████████████████████████████████████████████████████████████████████", + "\u001b[0m║██████████████████████████████████████████████████████████████████████████████████████████", + "\u001b[0m║███████████████████████████████████████████████████████████████████████████████████████████████", + "\u001b[0m║████████████████████████████████████████████████████████████████████████████████████████████████████", + "╚════════════════════════════════════════════════════════════════════════════════════════════════════" ], "labeless color chart": [ "", - "\u001b[0m║\u001b[38;5;160m██████\u001b[0m", - "\u001b[0m║\u001b[32m█████████████\u001b[0m", - "\u001b[0m║\u001b[38;5;227m███████████████████\u001b[0m", - "\u001b[0m║\u001b[34m█████████████████████████\u001b[0m", - "\u001b[0m║\u001b[35m███████████████████████████████\u001b[0m", - "\u001b[0m║\u001b[38;5;219m██████████████████████████████████████\u001b[0m", - "\u001b[0m║\u001b[96m████████████████████████████████████████████\u001b[0m", - "\u001b[0m║\u001b[38;5;215m██████████████████████████████████████████████████\u001b[0m", - "╚══════════════════════════════════════════════════" + "\u001b[0m║\u001b[38;5;160m█████████████\u001b[0m", + "\u001b[0m║\u001b[32m█████████████████████████\u001b[0m", + "\u001b[0m║\u001b[38;5;227m██████████████████████████████████████\u001b[0m", + "\u001b[0m║\u001b[34m██████████████████████████████████████████████████\u001b[0m", + "\u001b[0m║\u001b[35m███████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[0m║\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[0m║\u001b[96m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[0m║\u001b[38;5;215m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "╚════════════════════════════════════════════════════════════════════════════════════════════════════" ], "pastel theme": [ "", - "\u001b[31mred \u001b[0m╢\u001b[0m\u001b[31m██████\u001b[0m", - "\u001b[38;5;49mgreen \u001b[0m╢\u001b[0m\u001b[38;5;49m█████████████\u001b[0m", - "\u001b[38;5;228myellow \u001b[0m╢\u001b[0m\u001b[38;5;228m███████████████████\u001b[0m", - "\u001b[38;5;39mblue \u001b[0m╢\u001b[0m\u001b[38;5;39m█████████████████████████\u001b[0m", - "\u001b[38;5;147mpurple \u001b[0m╢\u001b[0m\u001b[38;5;147m███████████████████████████████\u001b[0m", - "\u001b[38;5;219mpink \u001b[0m╢\u001b[0m\u001b[38;5;219m██████████████████████████████████████\u001b[0m", - "\u001b[38;5;159mcyan \u001b[0m╢\u001b[0m\u001b[38;5;159m████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;209morange \u001b[0m╢\u001b[0m\u001b[38;5;209m██████████████████████████████████████████████████\u001b[0m", - " ╚══════════════════════════════════════════════════" + "\u001b[31mred \u001b[0m╢\u001b[0m\u001b[31m█████████████\u001b[0m", + "\u001b[38;5;49mgreen \u001b[0m╢\u001b[0m\u001b[38;5;49m█████████████████████████\u001b[0m", + "\u001b[38;5;228myellow \u001b[0m╢\u001b[0m\u001b[38;5;228m██████████████████████████████████████\u001b[0m", + "\u001b[38;5;39mblue \u001b[0m╢\u001b[0m\u001b[38;5;39m██████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;147mpurple \u001b[0m╢\u001b[0m\u001b[38;5;147m███████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mpink \u001b[0m╢\u001b[0m\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;159mcyan \u001b[0m╢\u001b[0m\u001b[38;5;159m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;209morange \u001b[0m╢\u001b[0m\u001b[38;5;209m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" ], "lush theme": [ "", - "\u001b[38;5;196mred \u001b[0m╢\u001b[0m\u001b[38;5;196m██████\u001b[0m", - "\u001b[38;5;154mgreen \u001b[0m╢\u001b[0m\u001b[38;5;154m█████████████\u001b[0m", - "\u001b[38;5;226myellow \u001b[0m╢\u001b[0m\u001b[38;5;226m███████████████████\u001b[0m", - "\u001b[38;5;57mblue \u001b[0m╢\u001b[0m\u001b[38;5;57m█████████████████████████\u001b[0m", - "\u001b[38;5;128mpurple \u001b[0m╢\u001b[0m\u001b[38;5;128m███████████████████████████████\u001b[0m", - "\u001b[38;5;198mpink \u001b[0m╢\u001b[0m\u001b[38;5;198m██████████████████████████████████████\u001b[0m", - "\u001b[38;5;87mcyan \u001b[0m╢\u001b[0m\u001b[38;5;87m████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;202morange \u001b[0m╢\u001b[0m\u001b[38;5;202m██████████████████████████████████████████████████\u001b[0m", - " ╚══════════════════════════════════════════════════" + "\u001b[38;5;196mred \u001b[0m╢\u001b[0m\u001b[38;5;196m█████████████\u001b[0m", + "\u001b[38;5;154mgreen \u001b[0m╢\u001b[0m\u001b[38;5;154m█████████████████████████\u001b[0m", + "\u001b[38;5;226myellow \u001b[0m╢\u001b[0m\u001b[38;5;226m██████████████████████████████████████\u001b[0m", + "\u001b[38;5;57mblue \u001b[0m╢\u001b[0m\u001b[38;5;57m██████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;128mpurple \u001b[0m╢\u001b[0m\u001b[38;5;128m███████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;198mpink \u001b[0m╢\u001b[0m\u001b[38;5;198m███████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;87mcyan \u001b[0m╢\u001b[0m\u001b[38;5;87m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;202morange \u001b[0m╢\u001b[0m\u001b[38;5;202m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" ], "standard theme": [ "", - "\u001b[38;5;9mred \u001b[0m╢\u001b[0m\u001b[38;5;9m██████\u001b[0m", - "\u001b[38;5;10mgreen \u001b[0m╢\u001b[0m\u001b[38;5;10m█████████████\u001b[0m", - "\u001b[38;5;11myellow \u001b[0m╢\u001b[0m\u001b[38;5;11m███████████████████\u001b[0m", - "\u001b[38;5;27mblue \u001b[0m╢\u001b[0m\u001b[38;5;27m█████████████████████████\u001b[0m", - "\u001b[38;5;105mpurple \u001b[0m╢\u001b[0m\u001b[38;5;105m███████████████████████████████\u001b[0m", - "\u001b[38;5;200mpink \u001b[0m╢\u001b[0m\u001b[38;5;200m██████████████████████████████████████\u001b[0m", - "\u001b[38;5;123mcyan \u001b[0m╢\u001b[0m\u001b[38;5;123m████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;214morange \u001b[0m╢\u001b[0m\u001b[38;5;214m██████████████████████████████████████████████████\u001b[0m", - " ╚══════════════════════════════════════════════════" + "\u001b[38;5;9mred \u001b[0m╢\u001b[0m\u001b[38;5;9m█████████████\u001b[0m", + "\u001b[38;5;10mgreen \u001b[0m╢\u001b[0m\u001b[38;5;10m█████████████████████████\u001b[0m", + "\u001b[38;5;11myellow \u001b[0m╢\u001b[0m\u001b[38;5;11m██████████████████████████████████████\u001b[0m", + "\u001b[38;5;27mblue \u001b[0m╢\u001b[0m\u001b[38;5;27m██████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;105mpurple \u001b[0m╢\u001b[0m\u001b[38;5;105m███████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;200mpink \u001b[0m╢\u001b[0m\u001b[38;5;200m███████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;123mcyan \u001b[0m╢\u001b[0m\u001b[38;5;123m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;214morange \u001b[0m╢\u001b[0m\u001b[38;5;214m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" ], "beach theme": [ "", - "\u001b[38;2;254;74;73mred \u001b[0m╢\u001b[0m\u001b[38;2;254;74;73m██████\u001b[0m", - "\u001b[38;2;42;183;202mgreen \u001b[0m╢\u001b[0m\u001b[38;2;42;183;202m█████████████\u001b[0m", - "\u001b[38;2;254;215;102myellow \u001b[0m╢\u001b[0m\u001b[38;2;254;215;102m███████████████████\u001b[0m", - "\u001b[38;2;146;196;238mblue \u001b[0m╢\u001b[0m\u001b[38;2;146;196;238m█████████████████████████\u001b[0m", - "\u001b[38;2;130;119;249mpurple \u001b[0m╢\u001b[0m\u001b[38;2;130;119;249m███████████████████████████████\u001b[0m", - "\u001b[38;2;222;82;133mpink \u001b[0m╢\u001b[0m\u001b[38;2;222;82;133m██████████████████████████████████████\u001b[0m", - "\u001b[38;2;0;255;255mcyan \u001b[0m╢\u001b[0m\u001b[38;2;0;255;255m████████████████████████████████████████████\u001b[0m", - "\u001b[38;2;247;126;2morange \u001b[0m╢\u001b[0m\u001b[38;2;247;126;2m██████████████████████████████████████████████████\u001b[0m", - " ╚══════════════════════════════════════════════════" + "\u001b[38;2;254;74;73mred \u001b[0m╢\u001b[0m\u001b[38;2;254;74;73m█████████████\u001b[0m", + "\u001b[38;2;42;183;202mgreen \u001b[0m╢\u001b[0m\u001b[38;2;42;183;202m█████████████████████████\u001b[0m", + "\u001b[38;2;254;215;102myellow \u001b[0m╢\u001b[0m\u001b[38;2;254;215;102m██████████████████████████████████████\u001b[0m", + "\u001b[38;2;146;196;238mblue \u001b[0m╢\u001b[0m\u001b[38;2;146;196;238m██████████████████████████████████████████████████\u001b[0m", + "\u001b[38;2;130;119;249mpurple \u001b[0m╢\u001b[0m\u001b[38;2;130;119;249m███████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;2;222;82;133mpink \u001b[0m╢\u001b[0m\u001b[38;2;222;82;133m███████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;2;0;255;255mcyan \u001b[0m╢\u001b[0m\u001b[38;2;0;255;255m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;2;247;126;2morange \u001b[0m╢\u001b[0m\u001b[38;2;247;126;2m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" ], "default theme": [ "", - "\u001b[38;5;160mred \u001b[0m╢\u001b[0m\u001b[38;5;160m██████\u001b[0m", - "\u001b[32mgreen \u001b[0m╢\u001b[0m\u001b[32m█████████████\u001b[0m", - "\u001b[38;5;227myellow \u001b[0m╢\u001b[0m\u001b[38;5;227m███████████████████\u001b[0m", - "\u001b[34mblue \u001b[0m╢\u001b[0m\u001b[34m█████████████████████████\u001b[0m", - "\u001b[35mpurple \u001b[0m╢\u001b[0m\u001b[35m███████████████████████████████\u001b[0m", - "\u001b[38;5;219mpink \u001b[0m╢\u001b[0m\u001b[38;5;219m██████████████████████████████████████\u001b[0m", - "\u001b[96mcyan \u001b[0m╢\u001b[0m\u001b[96m████████████████████████████████████████████\u001b[0m", - "\u001b[38;5;215morange \u001b[0m╢\u001b[0m\u001b[38;5;215m██████████████████████████████████████████████████\u001b[0m", - " ╚══════════════════════════════════════════════════" + "\u001b[38;5;160mred \u001b[0m╢\u001b[0m\u001b[38;5;160m█████████████\u001b[0m", + "\u001b[32mgreen \u001b[0m╢\u001b[0m\u001b[32m█████████████████████████\u001b[0m", + "\u001b[38;5;227myellow \u001b[0m╢\u001b[0m\u001b[38;5;227m██████████████████████████████████████\u001b[0m", + "\u001b[34mblue \u001b[0m╢\u001b[0m\u001b[34m██████████████████████████████████████████████████\u001b[0m", + "\u001b[35mpurple \u001b[0m╢\u001b[0m\u001b[35m███████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;219mpink \u001b[0m╢\u001b[0m\u001b[38;5;219m███████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[96mcyan \u001b[0m╢\u001b[0m\u001b[96m████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + "\u001b[38;5;215morange \u001b[0m╢\u001b[0m\u001b[38;5;215m████████████████████████████████████████████████████████████████████████████████████████████████████\u001b[0m", + " ╚════════════════════════════════════════════════════════════════════════════════════════════════════" ], "vertical": [ "", @@ -190,33 +190,33 @@ ], "labeless vertical chart": [ "", - "║ ██ ██ ██ ██ ", - "║ ██ ██ ██ ██ ██ ██ ", - "║ ██ ██ ██ ██ ██ ██ ██ ██ ", - "║ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ", - "║ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ", - "║ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ", - "║ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ", - "║ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ", - "║██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ", - "║██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ", - "╚════════════════════════════════════════════════════════════", - " 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 " + "║ ████████████████████", + "║ ██████████████████████████████", + "║ ████████████████████████████████████████", + "║ ██████████████████████████████████████████████████", + "║ ████████████████████████████████████████████████████████████", + "║ ██████████████████████████████████████████████████████████████████████", + "║ ████████████████████████████████████████████████████████████████████████████████", + "║ ██████████████████████████████████████████████████████████████████████████████████████████", + "║████████████████████████████████████████████████████████████████████████████████████████████████████", + "║████████████████████████████████████████████████████████████████████████████████████████████████████", + "╚════════════════════════════════════════════════════════════════════════════════════════════════════", + " 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 " ], "labeless color vertical chart": [ "", - "║ \u001b[96m██████\u001b[0m\u001b[38;5;215m██████\u001b[0m", - "║ \u001b[38;5;219m██████\u001b[0m\u001b[96m██████\u001b[0m\u001b[38;5;215m██████\u001b[0m", - "║ \u001b[38;5;219m██████\u001b[0m\u001b[96m██████\u001b[0m\u001b[38;5;215m██████\u001b[0m", - "║ \u001b[35m██████\u001b[0m\u001b[38;5;219m██████\u001b[0m\u001b[96m██████\u001b[0m\u001b[38;5;215m██████\u001b[0m", - "║ \u001b[34m██████\u001b[0m\u001b[35m██████\u001b[0m\u001b[38;5;219m██████\u001b[0m\u001b[96m██████\u001b[0m\u001b[38;5;215m██████\u001b[0m", - "║ \u001b[38;5;227m██████\u001b[0m\u001b[34m██████\u001b[0m\u001b[35m██████\u001b[0m\u001b[38;5;219m██████\u001b[0m\u001b[96m██████\u001b[0m\u001b[38;5;215m██████\u001b[0m", - "║ \u001b[32m██████\u001b[0m\u001b[38;5;227m██████\u001b[0m\u001b[34m██████\u001b[0m\u001b[35m██████\u001b[0m\u001b[38;5;219m██████\u001b[0m\u001b[96m██████\u001b[0m\u001b[38;5;215m██████\u001b[0m", - "║ \u001b[32m██████\u001b[0m\u001b[38;5;227m██████\u001b[0m\u001b[34m██████\u001b[0m\u001b[35m██████\u001b[0m\u001b[38;5;219m██████\u001b[0m\u001b[96m██████\u001b[0m\u001b[38;5;215m██████\u001b[0m", - "║\u001b[38;5;160m██████\u001b[0m\u001b[32m██████\u001b[0m\u001b[38;5;227m██████\u001b[0m\u001b[34m██████\u001b[0m\u001b[35m██████\u001b[0m\u001b[38;5;219m██████\u001b[0m\u001b[96m██████\u001b[0m\u001b[38;5;215m██████\u001b[0m", - "║\u001b[38;5;160m██████\u001b[0m\u001b[32m██████\u001b[0m\u001b[38;5;227m██████\u001b[0m\u001b[34m██████\u001b[0m\u001b[35m██████\u001b[0m\u001b[38;5;219m██████\u001b[0m\u001b[96m██████\u001b[0m\u001b[38;5;215m██████\u001b[0m", - "╚════════════════════════════════════════════════", - " 1 2 3 4 5 6 7 8 " + "║ \u001b[96m████████████ \u001b[0m\u001b[38;5;215m████████████ \u001b[0m", + "║ \u001b[38;5;219m████████████ \u001b[0m\u001b[96m████████████ \u001b[0m\u001b[38;5;215m████████████ \u001b[0m", + "║ \u001b[38;5;219m████████████ \u001b[0m\u001b[96m████████████ \u001b[0m\u001b[38;5;215m████████████ \u001b[0m", + "║ \u001b[35m████████████ \u001b[0m\u001b[38;5;219m████████████ \u001b[0m\u001b[96m████████████ \u001b[0m\u001b[38;5;215m████████████ \u001b[0m", + "║ \u001b[34m████████████ \u001b[0m\u001b[35m████████████ \u001b[0m\u001b[38;5;219m████████████ \u001b[0m\u001b[96m████████████ \u001b[0m\u001b[38;5;215m████████████ \u001b[0m", + "║ \u001b[38;5;227m████████████ \u001b[0m\u001b[34m████████████ \u001b[0m\u001b[35m████████████ \u001b[0m\u001b[38;5;219m████████████ \u001b[0m\u001b[96m████████████ \u001b[0m\u001b[38;5;215m████████████ \u001b[0m", + "║ \u001b[32m████████████ \u001b[0m\u001b[38;5;227m████████████ \u001b[0m\u001b[34m████████████ \u001b[0m\u001b[35m████████████ \u001b[0m\u001b[38;5;219m████████████ \u001b[0m\u001b[96m████████████ \u001b[0m\u001b[38;5;215m████████████ \u001b[0m", + "║ \u001b[32m████████████ \u001b[0m\u001b[38;5;227m████████████ \u001b[0m\u001b[34m████████████ \u001b[0m\u001b[35m████████████ \u001b[0m\u001b[38;5;219m████████████ \u001b[0m\u001b[96m████████████ \u001b[0m\u001b[38;5;215m████████████ \u001b[0m", + "║\u001b[38;5;160m████████████ \u001b[0m\u001b[32m████████████ \u001b[0m\u001b[38;5;227m████████████ \u001b[0m\u001b[34m████████████ \u001b[0m\u001b[35m████████████ \u001b[0m\u001b[38;5;219m████████████ \u001b[0m\u001b[96m████████████ \u001b[0m\u001b[38;5;215m████████████ \u001b[0m", + "║\u001b[38;5;160m████████████ \u001b[0m\u001b[32m████████████ \u001b[0m\u001b[38;5;227m████████████ \u001b[0m\u001b[34m████████████ \u001b[0m\u001b[35m████████████ \u001b[0m\u001b[38;5;219m████████████ \u001b[0m\u001b[96m████████████ \u001b[0m\u001b[38;5;215m████████████ \u001b[0m", + "╚════════════════════════════════════════════════════════════════════════════════════════════════════════", + " 1 2 3 4 5 6 7 8 " ], "pastel theme vertical": [ "", diff --git a/ts/char_ts_cii/test.ts b/ts/char_ts_cii/test.ts index 9db62da..8f54a64 100644 --- a/ts/char_ts_cii/test.ts +++ b/ts/char_ts_cii/test.ts @@ -20,8 +20,8 @@ for (let i = 0; i < colors.length; i++) { const chart1 = new Chartscii(data, { colorLabels: true, labels: false, - width: 100, - height: 10, + // width: 100, + // height: 10, // barWidth: 1, // width: process.stdout.columns - 1, // orientation: 'vertical' From 54fab85de5010cf0cb6f0d41f16a6429645f6c3e Mon Sep 17 00:00:00 2001 From: Tal Hayut Date: Tue, 7 May 2024 17:14:27 +0300 Subject: [PATCH 18/18] chore: formatting --- ts/char_ts_cii/formatters/formatter.ts | 26 +++++++++++ ts/char_ts_cii/formatters/horizontal.ts | 22 ++-------- ts/char_ts_cii/formatters/vertical.ts | 57 +++++++------------------ ts/char_ts_cii/test.ts | 23 +++++----- ts/char_ts_cii/try.ts | 7 --- ts/char_ts_cii/types.ts | 10 ----- 6 files changed, 57 insertions(+), 88 deletions(-) create mode 100644 ts/char_ts_cii/formatters/formatter.ts delete mode 100644 ts/char_ts_cii/try.ts diff --git a/ts/char_ts_cii/formatters/formatter.ts b/ts/char_ts_cii/formatters/formatter.ts new file mode 100644 index 0000000..1a02416 --- /dev/null +++ b/ts/char_ts_cii/formatters/formatter.ts @@ -0,0 +1,26 @@ +import style from 'styl3'; +import { ChartOptions } from '../types'; + +abstract class ChartFormatter { + colors: Record; + + constructor(options: ChartOptions) { + this.colors = style({ theme: options.theme }); + } + + colorify(txt: string, color?: string) { + if (color) { + if (color.includes('#')) { + return this.colors.hex(color)`${txt}`; + } else if (color.match(/[0-9]/)) { + return this.colors.ansi(color)`${txt}`; + } else if (Array.isArray(color)) { + return this.colors.rgb(...color)`${txt}`; + } else { + return this.colors[color]`${txt}`; + } + } + } +} + +export default ChartFormatter; \ No newline at end of file diff --git a/ts/char_ts_cii/formatters/horizontal.ts b/ts/char_ts_cii/formatters/horizontal.ts index 7caec15..22ec9c6 100644 --- a/ts/char_ts_cii/formatters/horizontal.ts +++ b/ts/char_ts_cii/formatters/horizontal.ts @@ -1,27 +1,13 @@ -import { HorizontalChartDataFormatter, ChartOptions, ChartData, ChartPoint } from '../types'; +import { ChartOptions, ChartData, ChartPoint } from '../types'; import style from 'styl3'; +import ChartFormatter from './formatter'; -class HorizontalChartFormatter implements HorizontalChartDataFormatter { +class HorizontalChartFormatter extends ChartFormatter { private options: ChartOptions - private colors: Record; constructor(options: ChartOptions) { + super(options); this.options = options; - this.colors = style({ theme: this.options.theme }); - } - - colorify(txt: string, color?: string) { - if (color) { - if (color.includes('#')) { - return this.colors.hex(color)`${txt}`; - } else if (color.match(/[0-9]/)) { - return this.colors.ansi(color)`${txt}`; - } else if (Array.isArray(color)) { - return this.colors.rgb(...color)`${txt}`; - } else { - return this.colors[color]`${txt}`; - } - } } pad(space: number) { diff --git a/ts/char_ts_cii/formatters/vertical.ts b/ts/char_ts_cii/formatters/vertical.ts index 1db0847..f45b45c 100644 --- a/ts/char_ts_cii/formatters/vertical.ts +++ b/ts/char_ts_cii/formatters/vertical.ts @@ -1,14 +1,15 @@ -import { VerticalChartDataFormatter, ChartOptions, ChartData, ChartPoint } from '../types'; +import { ChartOptions, ChartData, ChartPoint } from '../types'; import style from 'styl3'; -class VerticalChartFormatter implements VerticalChartDataFormatter { +import ChartFormatter from './formatter'; + +class VerticalChartFormatter extends ChartFormatter { private chart: ChartPoint[]; private options: ChartOptions; - private colors: Record; constructor(chart: ChartData, options: ChartOptions) { + super(options); this.chart = [...chart.values()] this.options = options; - this.colors = style({ theme: this.options.theme }); } public format(): string { @@ -21,43 +22,21 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { const padding = this.options.padding || defaultPadding - const verticalChart = this.initializeVerticalChart(maxHeight, padding); + const verticalChart = this.buildVerticalChart(maxHeight, padding); - this.populateChart(verticalChart, maxHeight, padding, barWidth); + this.formatChart(verticalChart, maxHeight, padding, barWidth); return this.composeFinalChart(verticalChart, barWidth, padding); } - colorify(txt: string, color?: string) { - if (color) { - if (color.includes('#')) { - return this.colors.hex(color)`${txt}`; - } else if (color.match(/[0-9]/)) { - return this.colors.ansi(color)`${txt}`; - } else if (Array.isArray(color)) { - return this.colors.rgb(...color)`${txt}`; - } else { - return this.colors[color]`${txt}`; - } - } - } - private getMaxHeight(): number { return this.options.max.scaled; } - private getMaxLabelWidth(): number { - if (this.options.labels) { - return this.options.max.label; - } - - return 0; - } - - private initializeVerticalChart(maxHeight: number, padding: number): string[][] { + private buildVerticalChart(maxHeight: number, padding: number): string[][] { return Array(maxHeight).fill('').map(() => Array(this.chart.length).fill('').map(() => ' '.repeat(padding))); } - private populateChart(verticalChart: string[][], maxHeight: number, padding: number, barWidth: number): void { + private formatChart(verticalChart: string[][], maxHeight: number, padding: number, barWidth: number): void { this.chart.forEach((point, index) => { const value = point.scaled; const height = Math.round((value / maxHeight) * maxHeight); @@ -115,12 +94,12 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { return label; } - private formatLabels(verticalChart: string[][], barWidth: number, padding: number) { + private formatLabels(barWidth: number, padding: number) { const formatted: string[] = []; this.chart.forEach((point, i) => { - const diff = barWidth> point.label.length ? barWidth - point.label.length : point.label.length - barWidth; const padLeft = i === 0 ? Math.floor(padding / 2) + 1 : 0; - const padRight = Math.abs((padding +barWidth) - point.label.length); + const padRight = Math.abs((padding + barWidth) - point.label.length); + formatted.push(' '.repeat(padLeft) + this.formatLabel(point) + ' '.repeat(padRight)); }) @@ -137,8 +116,8 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { if (!this.options.naked) { chart.unshift(this.makeChartLabel()); - chart.push(this.makeVerticalChartBottom(verticalChart, barWidth, padding)); - chart.push(this.formatLabels(verticalChart, barWidth, padding)); + chart.push(this.makeVerticalChartBottom(barWidth, padding)); + chart.push(this.formatLabels(barWidth, padding)); } return chart.join('\n'); } @@ -147,13 +126,7 @@ class VerticalChartFormatter implements VerticalChartDataFormatter { return this.options.label; } - private stripAnsi(str: string) { - // const ansiRegex = /[\u001b\u009b][[(][()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=>; \ No newline at end of file

AltStyle によって変換されたページ (->オリジナル) /