├── .gitignore
├── .npmignore
├── LICENSE
├── README.md
├── examples
├── dashboard.ts
├── get-started.ts
├── multi-series.ts
└── single.ts
├── package-lock.json
├── package.json
├── src
├── axis.ts
├── enum.ts
├── index.ts
├── label.ts
├── multi-plot.ts
├── plot.ts
└── utils.ts
├── tsconfig.json
└── tsconfig.lib.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /lib
6 | /tmp
7 | /out
8 | /docs
9 | /out-tsc
10 | # Only exists if Bazel was run
11 | /bazel-out
12 | .angular
13 |
14 | # dependencies
15 | /node_modules
16 |
17 | # profiling files
18 | chrome-profiler-events*.json
19 |
20 | # IDEs and editors
21 | /.idea
22 | .project
23 | .classpath
24 | .c9/
25 | *.launch
26 | .settings/
27 | *.sublime-workspace
28 |
29 | # IDE - VSCode
30 | .vscode/*
31 | !.vscode/settings.json
32 | !.vscode/tasks.json
33 | !.vscode/launch.json
34 | !.vscode/extensions.json
35 | .history/*
36 |
37 | # misc
38 | /.sass-cache
39 | /connect.lock
40 | /coverage
41 | /libpeerconnection.log
42 | npm-debug.log
43 | yarn-error.log
44 | testem.log
45 | /typings
46 |
47 | # System Files
48 | .DS_Store
49 | Thumbs.db
50 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | examples/
3 | node_modules/
4 | src/
5 |
6 | .gitignore
7 | tsconfig.json
8 | tsconfig.lib.json
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2023, Alexander
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright notice,
12 | this list of conditions and the following disclaimer in the documentation
13 | and/or other materials provided with the distribution.
14 |
15 | 3. Neither the name of the copyright holder nor the names of its
16 | contributors may be used to endorse or promote products derived from
17 | this software without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # text-graph.js
2 |
3 |
4 |
5 |
6 |
7 | `text-graph.js` is a compact and easy-to-use JavaScript/TypeScript library. It lets you create charts in the terminal and browser console. You can make line charts and build a dashboard with multiple charts, all without any extarnal dependencies. It has features for different axis and data scaling methods. Plus, it supports adding colors to your charts.
8 |
9 | [](https://badge.fury.io/js/text-graph.js)
10 |
11 | ## Features
12 |
13 | - Create line charts
14 | - Drawing multiple series on one plot
15 | - Creating dashboards with multiple charts
16 | - Colors for chart elements
17 | - Built-in axis scale functions (i.e. log)
18 | - Built-in different data overflow handling functions (i.e. linear scale, clapm, etc)
19 | - Built-in different data compression functions (i.e. mean, max, etc)
20 |
21 | ## Installation
22 |
23 | ```shell
24 | npm install text-graph.js
25 | ```
26 |
27 | ### Run from source
28 |
29 | ```shell
30 | # clone repo
31 | git clone https://github.com/DrA1ex/text-graph.js.git
32 | cd ./text-graph.js
33 |
34 | # install dependencies
35 | npm install
36 |
37 | # Run example
38 | npx tsx ./examples/dashboard.ts
39 | ```
40 |
41 | ## Get Started
42 |
43 | ```javascript
44 | // Importing the Plot class
45 | import {Plot} from 'text-graph.js';
46 |
47 | // Creating a new instance of the Plot class with a width of 80 characters and height of 20 characters
48 | const plot = new Plot(80, 20);
49 |
50 | // Adding a new series to the plot and storing its ID
51 | const id = plot.addSeries();
52 |
53 | // Defining a function that takes a number "x" as input and calculates a mathematical expression
54 | const fn = (x) => Math.pow(Math.sin(x), 3) + Math.pow(Math.cos(x), 3) - 1.5 * Math.sin(x) * Math.cos(x);
55 |
56 | // Iterating over a range of values from -2 to just below 2, incrementing by 0.05 at each step
57 | for (let x = -2; x < 2; x += 0.05) {
58 | // Adding an entry to the series with the given ID, calculated using the function "fn"
59 | plot.addSeriesEntry(id, fn(x));
60 | }
61 |
62 | // Printing the chart output to the console
63 | console.log(plot.paint());
64 | ```
65 |
66 | Source code: [link](/examples/get-started.ts)
67 |
68 | ## Usage
69 |
70 | To use `text-graph.js`, follow these steps:
71 |
72 | 1. Import the necessary classes and enums:
73 |
74 | ```javascript
75 | import {
76 | Plot, LabelPositionFlags, PlotAxisScale, PlotSeriesAggregationFn, PlotSeriesOverflow, Color, BackgroundColor
77 | } from 'text-graph.js';
78 | ```
79 |
80 | 2. Define the plot options:
81 |
82 | ```javascript
83 | const plotOptions = {
84 | showAxis: true,
85 | title: 'Chart Title',
86 | horizontalBoundary: 1,
87 | verticalBoundary: 2,
88 | titlePosition: LabelPositionFlags.top,
89 | titleForeground: Color.blue,
90 | titleBackground: BackgroundColor.black,
91 | axisLabelsFraction: 4,
92 | axisScale: PlotAxisScale.linear,
93 | aggregation: PlotSeriesAggregationFn.mean,
94 | zoom: false,
95 | }
96 | ```
97 |
98 | 3. Create a plot instance:
99 |
100 | ```javascript
101 | const width = 60;
102 | const height = 20;
103 | const plot = new Plot(width, height, plotOptions);
104 | ```
105 |
106 | 4. Define the series configurations:
107 |
108 | ```javascript
109 | const plotSeriesConfig1 = {
110 | color: Color.cyan,
111 | overflow: PlotSeriesOverflow.logScale
112 | };
113 |
114 | const plotSeriesConfig2 = {
115 | color: Color.magenta,
116 | overflow: PlotSeriesOverflow.clamp
117 | };
118 | ```
119 |
120 | 5. Add plot series to the plot:
121 |
122 | ```javascript
123 | const seriesId1 = plot.addSeries(plotSeriesConfig1);
124 | const seriesId2 = plot.addSeries(plotSeriesConfig2);
125 | ```
126 |
127 | 6. Option 1: Iterate over your data and update the plot:
128 |
129 | ```javascript
130 | const data1 = [1, 2, 3];
131 | for (const value of data1) {
132 | plot.addSeriesEntry(seriesId1, value);
133 | }
134 |
135 | const data2 = [0, -1, -2];
136 | for (const value of data2) {
137 | plot.addSeriesEntry(seriesId2, value);
138 | }
139 | ```
140 |
141 | 6. Option 2: Populate all data to the plot:
142 | ```javascript
143 | plot.addSeriesRange(seriesId1, [1, 2, 3]);
144 | plot.addSeriesRange(seriesId2, [0, -1, -2]);
145 | ```
146 |
147 | 7. Display the plot:
148 | ```javascript
149 | const chartData = plot.paint();
150 | console.log(chartData);
151 | ```
152 |
153 | ## Examples
154 |
155 | ### Single Series Chart
156 |
157 |
158 |
159 | Source code: [link](/examples/single.ts)
160 |
161 | ### Multi-line Series Chart
162 |
163 |
164 |
165 | Source code: [link](/examples/multi-series.ts)
166 |
167 | ### Dashboard
168 |
169 |
170 |
171 | Source code: [link](/examples/dashboard.ts)
172 |
173 | ### Neural network training dashboard
174 |
175 |
176 |
177 | Project: [link](https://github.com/DrA1ex/mind-net.js)
178 |
179 | ### Snippets
180 |
181 | #### Fast plot drawing
182 |
183 | ```javascript
184 | const data = new Array(200);
185 | for (let i = 0; i < data.length; i++) {
186 | data[i] = Math.sin(0.3 * i) * Math.cos(0.6 * i) - Math.sin(i * Math.PI / 50) * Math.abs(i - 100) / 30
187 | }
188 |
189 | console.log(Plot.plot(data));
190 | ```
191 |
192 |
193 |
194 | #### Axis scale
195 |
196 | ```javascript
197 | const data = new Array(300);
198 | for (let i = 0; i < data.length; i++) {
199 | data[i] = Math.sin(0.3 * i) * Math.cos(0.6 * i) - Math.sin(i * Math.PI / 50) * Math.abs(i - 100) / 30
200 | }
201 |
202 | console.log(Plot.plot(data, {axisScale: PlotAxisScale.log}));
203 | ```
204 |
205 |
206 |
207 | #### Series data zoom
208 |
209 | ```javascript
210 | const data = [1, 2, 3]
211 | console.log(Plot.plot(data, {zoom: true}));
212 | ```
213 |
214 |
215 |
216 |
217 | #### Series scale on overflow
218 |
219 | ```javascript
220 | const data = new Array(300);
221 | for (let i = 0; i < data.length; i++) {
222 | data[i] = Math.sin(0.3 * i) * Math.cos(0.6 * i) - Math.sin(i * Math.PI / 50) * Math.abs(i - 100) / 30
223 | }
224 |
225 | console.log(Plot.plot(data, {}, {overflow: PlotSeriesOverflow.logScale}));
226 | ```
227 |
228 |
229 |
230 | #### Series color
231 |
232 | ```javascript
233 | const data = new Array(300);
234 | for (let i = 0; i < data.length; i++) {
235 | data[i] = Math.sin(0.3 * i) * Math.cos(0.6 * i) - Math.sin(i * Math.PI / 50) * Math.abs(i - 100) / 30
236 | }
237 |
238 | console.log(Plot.plot(data, {}, {color: Color.green}));
239 | ```
240 |
241 |
242 |
243 | #### Different height
244 |
245 | ```javascript
246 | const data = new Array(200);
247 | for (let i = 0; i < data.length; i++) {
248 | data[i] = Math.sin(0.3 * i) * Math.cos(0.6 * i) - Math.sin(i * Math.PI / 50) * Math.abs(i - 100) / 30
249 | }
250 |
251 | console.log(Plot.plot(data, {height: 5}));
252 | ```
253 |
254 |
255 |
256 |
257 | ## License
258 |
259 | `text-graph.js` is released under the [BSD-3-Clause License](/LICENSE).
260 |
--------------------------------------------------------------------------------
/examples/dashboard.ts:
--------------------------------------------------------------------------------
1 | import {Color, BackgroundColor, MultiPlotChart, PlotAxisScale, PlotSeriesAggregationFn, PlotSeriesOverflow} from "../src";
2 |
3 | const chart = new MultiPlotChart({
4 | title: "Dashboard chart",
5 | titleBoundary: 2,
6 | titleSpacing: 8,
7 | titleForeground: Color.blue,
8 | titleBackground: BackgroundColor.black,
9 | });
10 |
11 | chart.addPlot({xOffset: 0, yOffset: 0, width: 40, height: 31}, {
12 | title: "overflow: skip",
13 | });
14 |
15 | chart.addPlot({xOffset: 42, yOffset: 0, width: 60, height: 15}, {
16 | title: "overflow: logScale (agg: max)",
17 | axisScale: PlotAxisScale.log,
18 | });
19 |
20 | chart.addPlot({xOffset: 42, yOffset: 16, width: 60, height: 15}, {
21 | title: "overflow: linearScale (agg: mean)",
22 | axisScale: PlotAxisScale.logInverted,
23 | aggregation: PlotSeriesAggregationFn.mean
24 | });
25 |
26 | chart.addPlotSeries(0, {color: Color.red, overflow: PlotSeriesOverflow.clamp});
27 | chart.addPlotSeries(1, {color: Color.blue, overflow: PlotSeriesOverflow.linearScale});
28 | chart.addPlotSeries(2, {color: Color.yellow});
29 |
30 | let delay = 66; // Delay in milliseconds
31 |
32 | for (let i = 0; i < 2000; i++) {
33 | setTimeout(() => {
34 | chart.addSeriesEntry(0, 0, Math.cos(i * Math.PI / 15));
35 | chart.addSeriesEntry(1, 0, Math.sin(i * Math.PI / 30) * 100 + 2);
36 | chart.addSeriesEntry(2, 0, Math.cos(i * Math.PI / 30) * 100 + 2);
37 |
38 | const chartData = chart.paint();
39 | console.clear();
40 | console.log(chartData);
41 | }, delay * i);
42 | }
--------------------------------------------------------------------------------
/examples/get-started.ts:
--------------------------------------------------------------------------------
1 | // Importing the Plot class
2 | import {Plot} from "../src";
3 |
4 | // Creating a new instance of the Plot class with a width of 80 characters and height of 20 characters
5 | const plot = new Plot(80, 20);
6 |
7 | // Adding a new series to the plot and storing its ID
8 | const id = plot.addSeries();
9 |
10 | // Defining a function that takes a number "x" as input and calculates a mathematical expression
11 | const fn = (x: number) => Math.pow(Math.sin(x), 3) + Math.pow(Math.cos(x), 3) - 1.5 * Math.sin(x) * Math.cos(x);
12 |
13 | // Iterating over a range of values from -2 to just below 2, incrementing by 0.05 at each step
14 | for (let x = -2; x < 2; x += 0.05) {
15 | // Adding an entry to the series with the given ID, calculated using the function "fn"
16 | plot.addSeriesEntry(id, fn(x));
17 | }
18 |
19 | // Printing the chart output to the console
20 | console.log(plot.paint());
--------------------------------------------------------------------------------
/examples/multi-series.ts:
--------------------------------------------------------------------------------
1 | import {Plot, Color, PlotAxisScale, PlotSeriesAggregationFn, PlotSeriesOverflow, LabelPositionFlags} from "../src";
2 |
3 | const plotOptions = {
4 | showAxis: true, // Show vertical axis
5 | title: "Multi-Series Demo", // Title of the chart
6 | titlePosition: LabelPositionFlags.top, // Position of the title
7 | axisScale: PlotAxisScale.linear, // Scale of the axis
8 | aggregation: PlotSeriesAggregationFn.mean, // Aggregation type for data points
9 | };
10 |
11 | const plot = new Plot(80, 20, plotOptions);
12 |
13 | const scale = PlotSeriesOverflow.linearScale // Overflow behavior of the series
14 | const seriesConfig1 = {
15 | color: Color.red, // Color of the first series
16 | overflow: scale
17 | };
18 |
19 | const seriesConfig2 = {
20 | color: Color.green, // Color of the second series
21 | overflow: scale
22 | };
23 |
24 | const seriesConfig3 = {
25 | color: Color.cyan, // Color of the third series
26 | overflow: scale
27 | };
28 |
29 | const seriesId1 = plot.addSeries(seriesConfig1);
30 | const seriesId2 = plot.addSeries(seriesConfig2);
31 | const seriesId3 = plot.addSeries(seriesConfig3);
32 |
33 | const fn1 = (x: number) => Math.sin(x) * Math.exp(-0.1 * x);
34 | const fn2 = (x: number) => 0.8 * Math.sin(x) + 0.6 * Math.sin(2 * x) + 0.4 * Math.sin(3 * x);
35 | const fn3 = (x: number) => Math.sin(x) * Math.cos(2 * x) + Math.cos(x) * Math.sin(2 * x);
36 |
37 | const delay = 66;
38 |
39 | async function draw() {
40 | for (let x = -2; x <= 2; x += 0.03) {
41 | plot.addSeriesEntry(seriesId1, fn1(x));
42 | plot.addSeriesEntry(seriesId2, fn2(x));
43 | plot.addSeriesEntry(seriesId3, fn3(x));
44 |
45 | const chartData = plot.paint();
46 | console.clear();
47 | console.log(chartData);
48 |
49 | await _delay(delay);
50 | }
51 | }
52 |
53 | // Start animated drawing
54 | draw();
55 |
56 | // Auxiliary function to avoid setTimeout in loop
57 | function _delay(d: number) { return new Promise(resolve => setTimeout(resolve, d))}
--------------------------------------------------------------------------------
/examples/single.ts:
--------------------------------------------------------------------------------
1 | import {Plot, Color, PlotAxisScale, PlotSeriesAggregationFn, PlotSeriesOverflow, LabelPositionFlags} from "../src";
2 |
3 | // Define the plot options
4 | const plotOptions = {
5 | showAxis: true,
6 | horizontalBoundary: 0,
7 | verticalBoundary: 1,
8 | title: 'Sample Line Chart',
9 | titlePosition: LabelPositionFlags.top,
10 | axisScale: PlotAxisScale.linear,
11 | aggregation: PlotSeriesAggregationFn.skip,
12 | };
13 |
14 | // Add a plot to the chart
15 | const plot = new Plot(80, 20, plotOptions);
16 |
17 | // Define the series configuration
18 | const seriesConfig = {
19 | color: Color.yellow,
20 | overflow: PlotSeriesOverflow.linearScale,
21 | };
22 |
23 | // Add new plot series
24 | const seriesId = plot.addSeries(seriesConfig);
25 |
26 | // Define function
27 | const fn = (x: number) => -Math.pow(x, 2) + plot.width * x;
28 |
29 | // Add data entries to the series
30 | for (let i = 0; i <= plot.width; i++) {
31 | plot.addSeriesEntry(seriesId, fn(i));
32 | }
33 |
34 | // Generate and print the chart data
35 | const chartData = plot.paint();
36 | console.log(chartData);
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "text-graph.js",
3 | "lockfileVersion": 3,
4 | "requires": true,
5 | "packages": {
6 | "": {
7 | "name": "text-graph.js",
8 | "license": "BSD 3-Clause",
9 | "devDependencies": {
10 | "esbuild": "^0.19.3",
11 | "ts-loader": "^9.4.4",
12 | "tsx": "^3.12.7",
13 | "typescript": "^5.1.6"
14 | },
15 | "version": "1.1.2"
16 | },
17 | "node_modules/@esbuild-kit/cjs-loader": {
18 | "version": "2.4.2",
19 | "resolved": "https://registry.npmjs.org/@esbuild-kit/cjs-loader/-/cjs-loader-2.4.2.tgz",
20 | "integrity": "sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==",
21 | "dev": true,
22 | "dependencies": {
23 | "@esbuild-kit/core-utils": "^3.0.0",
24 | "get-tsconfig": "^4.4.0"
25 | }
26 | },
27 | "node_modules/@esbuild-kit/core-utils": {
28 | "version": "3.1.0",
29 | "resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.1.0.tgz",
30 | "integrity": "sha512-Uuk8RpCg/7fdHSceR1M6XbSZFSuMrxcePFuGgyvsBn+u339dk5OeL4jv2EojwTN2st/unJGsVm4qHWjWNmJ/tw==",
31 | "dev": true,
32 | "dependencies": {
33 | "esbuild": "~0.17.6",
34 | "source-map-support": "^0.5.21"
35 | }
36 | },
37 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-arm": {
38 | "version": "0.17.19",
39 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz",
40 | "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==",
41 | "cpu": [
42 | "arm"
43 | ],
44 | "dev": true,
45 | "optional": true,
46 | "os": [
47 | "android"
48 | ],
49 | "engines": {
50 | "node": ">=12"
51 | }
52 | },
53 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-arm64": {
54 | "version": "0.17.19",
55 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz",
56 | "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==",
57 | "cpu": [
58 | "arm64"
59 | ],
60 | "dev": true,
61 | "optional": true,
62 | "os": [
63 | "android"
64 | ],
65 | "engines": {
66 | "node": ">=12"
67 | }
68 | },
69 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-x64": {
70 | "version": "0.17.19",
71 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz",
72 | "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==",
73 | "cpu": [
74 | "x64"
75 | ],
76 | "dev": true,
77 | "optional": true,
78 | "os": [
79 | "android"
80 | ],
81 | "engines": {
82 | "node": ">=12"
83 | }
84 | },
85 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/darwin-arm64": {
86 | "version": "0.17.19",
87 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz",
88 | "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==",
89 | "cpu": [
90 | "arm64"
91 | ],
92 | "dev": true,
93 | "optional": true,
94 | "os": [
95 | "darwin"
96 | ],
97 | "engines": {
98 | "node": ">=12"
99 | }
100 | },
101 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/darwin-x64": {
102 | "version": "0.17.19",
103 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz",
104 | "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==",
105 | "cpu": [
106 | "x64"
107 | ],
108 | "dev": true,
109 | "optional": true,
110 | "os": [
111 | "darwin"
112 | ],
113 | "engines": {
114 | "node": ">=12"
115 | }
116 | },
117 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/freebsd-arm64": {
118 | "version": "0.17.19",
119 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz",
120 | "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==",
121 | "cpu": [
122 | "arm64"
123 | ],
124 | "dev": true,
125 | "optional": true,
126 | "os": [
127 | "freebsd"
128 | ],
129 | "engines": {
130 | "node": ">=12"
131 | }
132 | },
133 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/freebsd-x64": {
134 | "version": "0.17.19",
135 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz",
136 | "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==",
137 | "cpu": [
138 | "x64"
139 | ],
140 | "dev": true,
141 | "optional": true,
142 | "os": [
143 | "freebsd"
144 | ],
145 | "engines": {
146 | "node": ">=12"
147 | }
148 | },
149 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-arm": {
150 | "version": "0.17.19",
151 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz",
152 | "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==",
153 | "cpu": [
154 | "arm"
155 | ],
156 | "dev": true,
157 | "optional": true,
158 | "os": [
159 | "linux"
160 | ],
161 | "engines": {
162 | "node": ">=12"
163 | }
164 | },
165 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-arm64": {
166 | "version": "0.17.19",
167 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz",
168 | "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==",
169 | "cpu": [
170 | "arm64"
171 | ],
172 | "dev": true,
173 | "optional": true,
174 | "os": [
175 | "linux"
176 | ],
177 | "engines": {
178 | "node": ">=12"
179 | }
180 | },
181 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-ia32": {
182 | "version": "0.17.19",
183 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz",
184 | "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==",
185 | "cpu": [
186 | "ia32"
187 | ],
188 | "dev": true,
189 | "optional": true,
190 | "os": [
191 | "linux"
192 | ],
193 | "engines": {
194 | "node": ">=12"
195 | }
196 | },
197 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-loong64": {
198 | "version": "0.17.19",
199 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz",
200 | "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==",
201 | "cpu": [
202 | "loong64"
203 | ],
204 | "dev": true,
205 | "optional": true,
206 | "os": [
207 | "linux"
208 | ],
209 | "engines": {
210 | "node": ">=12"
211 | }
212 | },
213 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-mips64el": {
214 | "version": "0.17.19",
215 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz",
216 | "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==",
217 | "cpu": [
218 | "mips64el"
219 | ],
220 | "dev": true,
221 | "optional": true,
222 | "os": [
223 | "linux"
224 | ],
225 | "engines": {
226 | "node": ">=12"
227 | }
228 | },
229 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-ppc64": {
230 | "version": "0.17.19",
231 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz",
232 | "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==",
233 | "cpu": [
234 | "ppc64"
235 | ],
236 | "dev": true,
237 | "optional": true,
238 | "os": [
239 | "linux"
240 | ],
241 | "engines": {
242 | "node": ">=12"
243 | }
244 | },
245 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-riscv64": {
246 | "version": "0.17.19",
247 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz",
248 | "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==",
249 | "cpu": [
250 | "riscv64"
251 | ],
252 | "dev": true,
253 | "optional": true,
254 | "os": [
255 | "linux"
256 | ],
257 | "engines": {
258 | "node": ">=12"
259 | }
260 | },
261 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-s390x": {
262 | "version": "0.17.19",
263 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz",
264 | "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==",
265 | "cpu": [
266 | "s390x"
267 | ],
268 | "dev": true,
269 | "optional": true,
270 | "os": [
271 | "linux"
272 | ],
273 | "engines": {
274 | "node": ">=12"
275 | }
276 | },
277 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-x64": {
278 | "version": "0.17.19",
279 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz",
280 | "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==",
281 | "cpu": [
282 | "x64"
283 | ],
284 | "dev": true,
285 | "optional": true,
286 | "os": [
287 | "linux"
288 | ],
289 | "engines": {
290 | "node": ">=12"
291 | }
292 | },
293 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/netbsd-x64": {
294 | "version": "0.17.19",
295 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz",
296 | "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==",
297 | "cpu": [
298 | "x64"
299 | ],
300 | "dev": true,
301 | "optional": true,
302 | "os": [
303 | "netbsd"
304 | ],
305 | "engines": {
306 | "node": ">=12"
307 | }
308 | },
309 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/openbsd-x64": {
310 | "version": "0.17.19",
311 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz",
312 | "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==",
313 | "cpu": [
314 | "x64"
315 | ],
316 | "dev": true,
317 | "optional": true,
318 | "os": [
319 | "openbsd"
320 | ],
321 | "engines": {
322 | "node": ">=12"
323 | }
324 | },
325 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/sunos-x64": {
326 | "version": "0.17.19",
327 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz",
328 | "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==",
329 | "cpu": [
330 | "x64"
331 | ],
332 | "dev": true,
333 | "optional": true,
334 | "os": [
335 | "sunos"
336 | ],
337 | "engines": {
338 | "node": ">=12"
339 | }
340 | },
341 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-arm64": {
342 | "version": "0.17.19",
343 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz",
344 | "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==",
345 | "cpu": [
346 | "arm64"
347 | ],
348 | "dev": true,
349 | "optional": true,
350 | "os": [
351 | "win32"
352 | ],
353 | "engines": {
354 | "node": ">=12"
355 | }
356 | },
357 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-ia32": {
358 | "version": "0.17.19",
359 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz",
360 | "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==",
361 | "cpu": [
362 | "ia32"
363 | ],
364 | "dev": true,
365 | "optional": true,
366 | "os": [
367 | "win32"
368 | ],
369 | "engines": {
370 | "node": ">=12"
371 | }
372 | },
373 | "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-x64": {
374 | "version": "0.17.19",
375 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz",
376 | "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==",
377 | "cpu": [
378 | "x64"
379 | ],
380 | "dev": true,
381 | "optional": true,
382 | "os": [
383 | "win32"
384 | ],
385 | "engines": {
386 | "node": ">=12"
387 | }
388 | },
389 | "node_modules/@esbuild-kit/core-utils/node_modules/esbuild": {
390 | "version": "0.17.19",
391 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz",
392 | "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==",
393 | "dev": true,
394 | "hasInstallScript": true,
395 | "bin": {
396 | "esbuild": "bin/esbuild"
397 | },
398 | "engines": {
399 | "node": ">=12"
400 | },
401 | "optionalDependencies": {
402 | "@esbuild/android-arm": "0.17.19",
403 | "@esbuild/android-arm64": "0.17.19",
404 | "@esbuild/android-x64": "0.17.19",
405 | "@esbuild/darwin-arm64": "0.17.19",
406 | "@esbuild/darwin-x64": "0.17.19",
407 | "@esbuild/freebsd-arm64": "0.17.19",
408 | "@esbuild/freebsd-x64": "0.17.19",
409 | "@esbuild/linux-arm": "0.17.19",
410 | "@esbuild/linux-arm64": "0.17.19",
411 | "@esbuild/linux-ia32": "0.17.19",
412 | "@esbuild/linux-loong64": "0.17.19",
413 | "@esbuild/linux-mips64el": "0.17.19",
414 | "@esbuild/linux-ppc64": "0.17.19",
415 | "@esbuild/linux-riscv64": "0.17.19",
416 | "@esbuild/linux-s390x": "0.17.19",
417 | "@esbuild/linux-x64": "0.17.19",
418 | "@esbuild/netbsd-x64": "0.17.19",
419 | "@esbuild/openbsd-x64": "0.17.19",
420 | "@esbuild/sunos-x64": "0.17.19",
421 | "@esbuild/win32-arm64": "0.17.19",
422 | "@esbuild/win32-ia32": "0.17.19",
423 | "@esbuild/win32-x64": "0.17.19"
424 | }
425 | },
426 | "node_modules/@esbuild-kit/esm-loader": {
427 | "version": "2.5.5",
428 | "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.5.5.tgz",
429 | "integrity": "sha512-Qwfvj/qoPbClxCRNuac1Du01r9gvNOT+pMYtJDapfB1eoGN1YlJ1BixLyL9WVENRx5RXgNLdfYdx/CuswlGhMw==",
430 | "dev": true,
431 | "dependencies": {
432 | "@esbuild-kit/core-utils": "^3.0.0",
433 | "get-tsconfig": "^4.4.0"
434 | }
435 | },
436 | "node_modules/@esbuild/android-arm": {
437 | "version": "0.19.3",
438 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.3.tgz",
439 | "integrity": "sha512-Lemgw4io4VZl9GHJmjiBGzQ7ONXRfRPHcUEerndjwiSkbxzrpq0Uggku5MxxrXdwJ+pTj1qyw4jwTu7hkPsgIA==",
440 | "cpu": [
441 | "arm"
442 | ],
443 | "dev": true,
444 | "optional": true,
445 | "os": [
446 | "android"
447 | ],
448 | "engines": {
449 | "node": ">=12"
450 | }
451 | },
452 | "node_modules/@esbuild/android-arm64": {
453 | "version": "0.19.3",
454 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.3.tgz",
455 | "integrity": "sha512-w+Akc0vv5leog550kjJV9Ru+MXMR2VuMrui3C61mnysim0gkFCPOUTAfzTP0qX+HpN9Syu3YA3p1hf3EPqObRw==",
456 | "cpu": [
457 | "arm64"
458 | ],
459 | "dev": true,
460 | "optional": true,
461 | "os": [
462 | "android"
463 | ],
464 | "engines": {
465 | "node": ">=12"
466 | }
467 | },
468 | "node_modules/@esbuild/android-x64": {
469 | "version": "0.19.3",
470 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.3.tgz",
471 | "integrity": "sha512-FKQJKkK5MXcBHoNZMDNUAg1+WcZlV/cuXrWCoGF/TvdRiYS4znA0m5Il5idUwfxrE20bG/vU1Cr5e1AD6IEIjQ==",
472 | "cpu": [
473 | "x64"
474 | ],
475 | "dev": true,
476 | "optional": true,
477 | "os": [
478 | "android"
479 | ],
480 | "engines": {
481 | "node": ">=12"
482 | }
483 | },
484 | "node_modules/@esbuild/darwin-arm64": {
485 | "version": "0.19.3",
486 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.3.tgz",
487 | "integrity": "sha512-kw7e3FXU+VsJSSSl2nMKvACYlwtvZB8RUIeVShIEY6PVnuZ3c9+L9lWB2nWeeKWNNYDdtL19foCQ0ZyUL7nqGw==",
488 | "cpu": [
489 | "arm64"
490 | ],
491 | "dev": true,
492 | "optional": true,
493 | "os": [
494 | "darwin"
495 | ],
496 | "engines": {
497 | "node": ">=12"
498 | }
499 | },
500 | "node_modules/@esbuild/darwin-x64": {
501 | "version": "0.19.3",
502 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.3.tgz",
503 | "integrity": "sha512-tPfZiwF9rO0jW6Jh9ipi58N5ZLoSjdxXeSrAYypy4psA2Yl1dAMhM71KxVfmjZhJmxRjSnb29YlRXXhh3GqzYw==",
504 | "cpu": [
505 | "x64"
506 | ],
507 | "dev": true,
508 | "optional": true,
509 | "os": [
510 | "darwin"
511 | ],
512 | "engines": {
513 | "node": ">=12"
514 | }
515 | },
516 | "node_modules/@esbuild/freebsd-arm64": {
517 | "version": "0.19.3",
518 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.3.tgz",
519 | "integrity": "sha512-ERDyjOgYeKe0Vrlr1iLrqTByB026YLPzTytDTz1DRCYM+JI92Dw2dbpRHYmdqn6VBnQ9Bor6J8ZlNwdZdxjlSg==",
520 | "cpu": [
521 | "arm64"
522 | ],
523 | "dev": true,
524 | "optional": true,
525 | "os": [
526 | "freebsd"
527 | ],
528 | "engines": {
529 | "node": ">=12"
530 | }
531 | },
532 | "node_modules/@esbuild/freebsd-x64": {
533 | "version": "0.19.3",
534 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.3.tgz",
535 | "integrity": "sha512-nXesBZ2Ad1qL+Rm3crN7NmEVJ5uvfLFPLJev3x1j3feCQXfAhoYrojC681RhpdOph8NsvKBBwpYZHR7W0ifTTA==",
536 | "cpu": [
537 | "x64"
538 | ],
539 | "dev": true,
540 | "optional": true,
541 | "os": [
542 | "freebsd"
543 | ],
544 | "engines": {
545 | "node": ">=12"
546 | }
547 | },
548 | "node_modules/@esbuild/linux-arm": {
549 | "version": "0.19.3",
550 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.3.tgz",
551 | "integrity": "sha512-zr48Cg/8zkzZCzDHNxXO/89bf9e+r4HtzNUPoz4GmgAkF1gFAFmfgOdCbR8zMbzFDGb1FqBBhdXUpcTQRYS1cQ==",
552 | "cpu": [
553 | "arm"
554 | ],
555 | "dev": true,
556 | "optional": true,
557 | "os": [
558 | "linux"
559 | ],
560 | "engines": {
561 | "node": ">=12"
562 | }
563 | },
564 | "node_modules/@esbuild/linux-arm64": {
565 | "version": "0.19.3",
566 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.3.tgz",
567 | "integrity": "sha512-qXvYKmXj8GcJgWq3aGvxL/JG1ZM3UR272SdPU4QSTzD0eymrM7leiZH77pvY3UetCy0k1xuXZ+VPvoJNdtrsWQ==",
568 | "cpu": [
569 | "arm64"
570 | ],
571 | "dev": true,
572 | "optional": true,
573 | "os": [
574 | "linux"
575 | ],
576 | "engines": {
577 | "node": ">=12"
578 | }
579 | },
580 | "node_modules/@esbuild/linux-ia32": {
581 | "version": "0.19.3",
582 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.3.tgz",
583 | "integrity": "sha512-7XlCKCA0nWcbvYpusARWkFjRQNWNGlt45S+Q18UeS///K6Aw8bB2FKYe9mhVWy/XLShvCweOLZPrnMswIaDXQA==",
584 | "cpu": [
585 | "ia32"
586 | ],
587 | "dev": true,
588 | "optional": true,
589 | "os": [
590 | "linux"
591 | ],
592 | "engines": {
593 | "node": ">=12"
594 | }
595 | },
596 | "node_modules/@esbuild/linux-loong64": {
597 | "version": "0.19.3",
598 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.3.tgz",
599 | "integrity": "sha512-qGTgjweER5xqweiWtUIDl9OKz338EQqCwbS9c2Bh5jgEH19xQ1yhgGPNesugmDFq+UUSDtWgZ264st26b3de8A==",
600 | "cpu": [
601 | "loong64"
602 | ],
603 | "dev": true,
604 | "optional": true,
605 | "os": [
606 | "linux"
607 | ],
608 | "engines": {
609 | "node": ">=12"
610 | }
611 | },
612 | "node_modules/@esbuild/linux-mips64el": {
613 | "version": "0.19.3",
614 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.3.tgz",
615 | "integrity": "sha512-gy1bFskwEyxVMFRNYSvBauDIWNggD6pyxUksc0MV9UOBD138dKTzr8XnM2R4mBsHwVzeuIH8X5JhmNs2Pzrx+A==",
616 | "cpu": [
617 | "mips64el"
618 | ],
619 | "dev": true,
620 | "optional": true,
621 | "os": [
622 | "linux"
623 | ],
624 | "engines": {
625 | "node": ">=12"
626 | }
627 | },
628 | "node_modules/@esbuild/linux-ppc64": {
629 | "version": "0.19.3",
630 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.3.tgz",
631 | "integrity": "sha512-UrYLFu62x1MmmIe85rpR3qou92wB9lEXluwMB/STDzPF9k8mi/9UvNsG07Tt9AqwPQXluMQ6bZbTzYt01+Ue5g==",
632 | "cpu": [
633 | "ppc64"
634 | ],
635 | "dev": true,
636 | "optional": true,
637 | "os": [
638 | "linux"
639 | ],
640 | "engines": {
641 | "node": ">=12"
642 | }
643 | },
644 | "node_modules/@esbuild/linux-riscv64": {
645 | "version": "0.19.3",
646 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.3.tgz",
647 | "integrity": "sha512-9E73TfyMCbE+1AwFOg3glnzZ5fBAFK4aawssvuMgCRqCYzE0ylVxxzjEfut8xjmKkR320BEoMui4o/t9KA96gA==",
648 | "cpu": [
649 | "riscv64"
650 | ],
651 | "dev": true,
652 | "optional": true,
653 | "os": [
654 | "linux"
655 | ],
656 | "engines": {
657 | "node": ">=12"
658 | }
659 | },
660 | "node_modules/@esbuild/linux-s390x": {
661 | "version": "0.19.3",
662 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.3.tgz",
663 | "integrity": "sha512-LlmsbuBdm1/D66TJ3HW6URY8wO6IlYHf+ChOUz8SUAjVTuaisfuwCOAgcxo3Zsu3BZGxmI7yt//yGOxV+lHcEA==",
664 | "cpu": [
665 | "s390x"
666 | ],
667 | "dev": true,
668 | "optional": true,
669 | "os": [
670 | "linux"
671 | ],
672 | "engines": {
673 | "node": ">=12"
674 | }
675 | },
676 | "node_modules/@esbuild/linux-x64": {
677 | "version": "0.19.3",
678 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.3.tgz",
679 | "integrity": "sha512-ogV0+GwEmvwg/8ZbsyfkYGaLACBQWDvO0Kkh8LKBGKj9Ru8VM39zssrnu9Sxn1wbapA2qNS6BiLdwJZGouyCwQ==",
680 | "cpu": [
681 | "x64"
682 | ],
683 | "dev": true,
684 | "optional": true,
685 | "os": [
686 | "linux"
687 | ],
688 | "engines": {
689 | "node": ">=12"
690 | }
691 | },
692 | "node_modules/@esbuild/netbsd-x64": {
693 | "version": "0.19.3",
694 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.3.tgz",
695 | "integrity": "sha512-o1jLNe4uzQv2DKXMlmEzf66Wd8MoIhLNO2nlQBHLtWyh2MitDG7sMpfCO3NTcoTMuqHjfufgUQDFRI5C+xsXQw==",
696 | "cpu": [
697 | "x64"
698 | ],
699 | "dev": true,
700 | "optional": true,
701 | "os": [
702 | "netbsd"
703 | ],
704 | "engines": {
705 | "node": ">=12"
706 | }
707 | },
708 | "node_modules/@esbuild/openbsd-x64": {
709 | "version": "0.19.3",
710 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.3.tgz",
711 | "integrity": "sha512-AZJCnr5CZgZOdhouLcfRdnk9Zv6HbaBxjcyhq0StNcvAdVZJSKIdOiPB9az2zc06ywl0ePYJz60CjdKsQacp5Q==",
712 | "cpu": [
713 | "x64"
714 | ],
715 | "dev": true,
716 | "optional": true,
717 | "os": [
718 | "openbsd"
719 | ],
720 | "engines": {
721 | "node": ">=12"
722 | }
723 | },
724 | "node_modules/@esbuild/sunos-x64": {
725 | "version": "0.19.3",
726 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.3.tgz",
727 | "integrity": "sha512-Acsujgeqg9InR4glTRvLKGZ+1HMtDm94ehTIHKhJjFpgVzZG9/pIcWW/HA/DoMfEyXmANLDuDZ2sNrWcjq1lxw==",
728 | "cpu": [
729 | "x64"
730 | ],
731 | "dev": true,
732 | "optional": true,
733 | "os": [
734 | "sunos"
735 | ],
736 | "engines": {
737 | "node": ">=12"
738 | }
739 | },
740 | "node_modules/@esbuild/win32-arm64": {
741 | "version": "0.19.3",
742 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.3.tgz",
743 | "integrity": "sha512-FSrAfjVVy7TifFgYgliiJOyYynhQmqgPj15pzLyJk8BUsnlWNwP/IAy6GAiB1LqtoivowRgidZsfpoYLZH586A==",
744 | "cpu": [
745 | "arm64"
746 | ],
747 | "dev": true,
748 | "optional": true,
749 | "os": [
750 | "win32"
751 | ],
752 | "engines": {
753 | "node": ">=12"
754 | }
755 | },
756 | "node_modules/@esbuild/win32-ia32": {
757 | "version": "0.19.3",
758 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.3.tgz",
759 | "integrity": "sha512-xTScXYi12xLOWZ/sc5RBmMN99BcXp/eEf7scUC0oeiRoiT5Vvo9AycuqCp+xdpDyAU+LkrCqEpUS9fCSZF8J3Q==",
760 | "cpu": [
761 | "ia32"
762 | ],
763 | "dev": true,
764 | "optional": true,
765 | "os": [
766 | "win32"
767 | ],
768 | "engines": {
769 | "node": ">=12"
770 | }
771 | },
772 | "node_modules/@esbuild/win32-x64": {
773 | "version": "0.19.3",
774 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.3.tgz",
775 | "integrity": "sha512-FbUN+0ZRXsypPyWE2IwIkVjDkDnJoMJARWOcFZn4KPPli+QnKqF0z1anvfaYe3ev5HFCpRDLLBDHyOALLppWHw==",
776 | "cpu": [
777 | "x64"
778 | ],
779 | "dev": true,
780 | "optional": true,
781 | "os": [
782 | "win32"
783 | ],
784 | "engines": {
785 | "node": ">=12"
786 | }
787 | },
788 | "node_modules/@jridgewell/gen-mapping": {
789 | "version": "0.3.3",
790 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
791 | "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
792 | "dev": true,
793 | "peer": true,
794 | "dependencies": {
795 | "@jridgewell/set-array": "^1.0.1",
796 | "@jridgewell/sourcemap-codec": "^1.4.10",
797 | "@jridgewell/trace-mapping": "^0.3.9"
798 | },
799 | "engines": {
800 | "node": ">=6.0.0"
801 | }
802 | },
803 | "node_modules/@jridgewell/resolve-uri": {
804 | "version": "3.1.1",
805 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
806 | "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
807 | "dev": true,
808 | "peer": true,
809 | "engines": {
810 | "node": ">=6.0.0"
811 | }
812 | },
813 | "node_modules/@jridgewell/set-array": {
814 | "version": "1.1.2",
815 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
816 | "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
817 | "dev": true,
818 | "peer": true,
819 | "engines": {
820 | "node": ">=6.0.0"
821 | }
822 | },
823 | "node_modules/@jridgewell/source-map": {
824 | "version": "0.3.5",
825 | "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz",
826 | "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==",
827 | "dev": true,
828 | "peer": true,
829 | "dependencies": {
830 | "@jridgewell/gen-mapping": "^0.3.0",
831 | "@jridgewell/trace-mapping": "^0.3.9"
832 | }
833 | },
834 | "node_modules/@jridgewell/sourcemap-codec": {
835 | "version": "1.4.15",
836 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
837 | "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
838 | "dev": true,
839 | "peer": true
840 | },
841 | "node_modules/@jridgewell/trace-mapping": {
842 | "version": "0.3.19",
843 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz",
844 | "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==",
845 | "dev": true,
846 | "peer": true,
847 | "dependencies": {
848 | "@jridgewell/resolve-uri": "^3.1.0",
849 | "@jridgewell/sourcemap-codec": "^1.4.14"
850 | }
851 | },
852 | "node_modules/@types/eslint": {
853 | "version": "8.44.2",
854 | "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.2.tgz",
855 | "integrity": "sha512-sdPRb9K6iL5XZOmBubg8yiFp5yS/JdUDQsq5e6h95km91MCYMuvp7mh1fjPEYUhvHepKpZOjnEaMBR4PxjWDzg==",
856 | "dev": true,
857 | "peer": true,
858 | "dependencies": {
859 | "@types/estree": "*",
860 | "@types/json-schema": "*"
861 | }
862 | },
863 | "node_modules/@types/eslint-scope": {
864 | "version": "3.7.4",
865 | "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz",
866 | "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==",
867 | "dev": true,
868 | "peer": true,
869 | "dependencies": {
870 | "@types/eslint": "*",
871 | "@types/estree": "*"
872 | }
873 | },
874 | "node_modules/@types/estree": {
875 | "version": "1.0.1",
876 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz",
877 | "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==",
878 | "dev": true,
879 | "peer": true
880 | },
881 | "node_modules/@types/json-schema": {
882 | "version": "7.0.12",
883 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz",
884 | "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==",
885 | "dev": true,
886 | "peer": true
887 | },
888 | "node_modules/@types/node": {
889 | "version": "20.4.9",
890 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.9.tgz",
891 | "integrity": "sha512-8e2HYcg7ohnTUbHk8focoklEQYvemQmu9M/f43DZVx43kHn0tE3BY/6gSDxS7k0SprtS0NHvj+L80cGLnoOUcQ==",
892 | "dev": true,
893 | "peer": true
894 | },
895 | "node_modules/@webassemblyjs/ast": {
896 | "version": "1.11.6",
897 | "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz",
898 | "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==",
899 | "dev": true,
900 | "peer": true,
901 | "dependencies": {
902 | "@webassemblyjs/helper-numbers": "1.11.6",
903 | "@webassemblyjs/helper-wasm-bytecode": "1.11.6"
904 | }
905 | },
906 | "node_modules/@webassemblyjs/floating-point-hex-parser": {
907 | "version": "1.11.6",
908 | "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz",
909 | "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==",
910 | "dev": true,
911 | "peer": true
912 | },
913 | "node_modules/@webassemblyjs/helper-api-error": {
914 | "version": "1.11.6",
915 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz",
916 | "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==",
917 | "dev": true,
918 | "peer": true
919 | },
920 | "node_modules/@webassemblyjs/helper-buffer": {
921 | "version": "1.11.6",
922 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz",
923 | "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==",
924 | "dev": true,
925 | "peer": true
926 | },
927 | "node_modules/@webassemblyjs/helper-numbers": {
928 | "version": "1.11.6",
929 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz",
930 | "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==",
931 | "dev": true,
932 | "peer": true,
933 | "dependencies": {
934 | "@webassemblyjs/floating-point-hex-parser": "1.11.6",
935 | "@webassemblyjs/helper-api-error": "1.11.6",
936 | "@xtuc/long": "4.2.2"
937 | }
938 | },
939 | "node_modules/@webassemblyjs/helper-wasm-bytecode": {
940 | "version": "1.11.6",
941 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz",
942 | "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==",
943 | "dev": true,
944 | "peer": true
945 | },
946 | "node_modules/@webassemblyjs/helper-wasm-section": {
947 | "version": "1.11.6",
948 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz",
949 | "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==",
950 | "dev": true,
951 | "peer": true,
952 | "dependencies": {
953 | "@webassemblyjs/ast": "1.11.6",
954 | "@webassemblyjs/helper-buffer": "1.11.6",
955 | "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
956 | "@webassemblyjs/wasm-gen": "1.11.6"
957 | }
958 | },
959 | "node_modules/@webassemblyjs/ieee754": {
960 | "version": "1.11.6",
961 | "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz",
962 | "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==",
963 | "dev": true,
964 | "peer": true,
965 | "dependencies": {
966 | "@xtuc/ieee754": "^1.2.0"
967 | }
968 | },
969 | "node_modules/@webassemblyjs/leb128": {
970 | "version": "1.11.6",
971 | "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz",
972 | "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==",
973 | "dev": true,
974 | "peer": true,
975 | "dependencies": {
976 | "@xtuc/long": "4.2.2"
977 | }
978 | },
979 | "node_modules/@webassemblyjs/utf8": {
980 | "version": "1.11.6",
981 | "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz",
982 | "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==",
983 | "dev": true,
984 | "peer": true
985 | },
986 | "node_modules/@webassemblyjs/wasm-edit": {
987 | "version": "1.11.6",
988 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz",
989 | "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==",
990 | "dev": true,
991 | "peer": true,
992 | "dependencies": {
993 | "@webassemblyjs/ast": "1.11.6",
994 | "@webassemblyjs/helper-buffer": "1.11.6",
995 | "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
996 | "@webassemblyjs/helper-wasm-section": "1.11.6",
997 | "@webassemblyjs/wasm-gen": "1.11.6",
998 | "@webassemblyjs/wasm-opt": "1.11.6",
999 | "@webassemblyjs/wasm-parser": "1.11.6",
1000 | "@webassemblyjs/wast-printer": "1.11.6"
1001 | }
1002 | },
1003 | "node_modules/@webassemblyjs/wasm-gen": {
1004 | "version": "1.11.6",
1005 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz",
1006 | "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==",
1007 | "dev": true,
1008 | "peer": true,
1009 | "dependencies": {
1010 | "@webassemblyjs/ast": "1.11.6",
1011 | "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
1012 | "@webassemblyjs/ieee754": "1.11.6",
1013 | "@webassemblyjs/leb128": "1.11.6",
1014 | "@webassemblyjs/utf8": "1.11.6"
1015 | }
1016 | },
1017 | "node_modules/@webassemblyjs/wasm-opt": {
1018 | "version": "1.11.6",
1019 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz",
1020 | "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==",
1021 | "dev": true,
1022 | "peer": true,
1023 | "dependencies": {
1024 | "@webassemblyjs/ast": "1.11.6",
1025 | "@webassemblyjs/helper-buffer": "1.11.6",
1026 | "@webassemblyjs/wasm-gen": "1.11.6",
1027 | "@webassemblyjs/wasm-parser": "1.11.6"
1028 | }
1029 | },
1030 | "node_modules/@webassemblyjs/wasm-parser": {
1031 | "version": "1.11.6",
1032 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz",
1033 | "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==",
1034 | "dev": true,
1035 | "peer": true,
1036 | "dependencies": {
1037 | "@webassemblyjs/ast": "1.11.6",
1038 | "@webassemblyjs/helper-api-error": "1.11.6",
1039 | "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
1040 | "@webassemblyjs/ieee754": "1.11.6",
1041 | "@webassemblyjs/leb128": "1.11.6",
1042 | "@webassemblyjs/utf8": "1.11.6"
1043 | }
1044 | },
1045 | "node_modules/@webassemblyjs/wast-printer": {
1046 | "version": "1.11.6",
1047 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz",
1048 | "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==",
1049 | "dev": true,
1050 | "peer": true,
1051 | "dependencies": {
1052 | "@webassemblyjs/ast": "1.11.6",
1053 | "@xtuc/long": "4.2.2"
1054 | }
1055 | },
1056 | "node_modules/@xtuc/ieee754": {
1057 | "version": "1.2.0",
1058 | "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
1059 | "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
1060 | "dev": true,
1061 | "peer": true
1062 | },
1063 | "node_modules/@xtuc/long": {
1064 | "version": "4.2.2",
1065 | "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
1066 | "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
1067 | "dev": true,
1068 | "peer": true
1069 | },
1070 | "node_modules/acorn": {
1071 | "version": "8.10.0",
1072 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
1073 | "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
1074 | "dev": true,
1075 | "peer": true,
1076 | "bin": {
1077 | "acorn": "bin/acorn"
1078 | },
1079 | "engines": {
1080 | "node": ">=0.4.0"
1081 | }
1082 | },
1083 | "node_modules/acorn-import-assertions": {
1084 | "version": "1.9.0",
1085 | "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz",
1086 | "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==",
1087 | "dev": true,
1088 | "peer": true,
1089 | "peerDependencies": {
1090 | "acorn": "^8"
1091 | }
1092 | },
1093 | "node_modules/ajv": {
1094 | "version": "6.12.6",
1095 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
1096 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
1097 | "dev": true,
1098 | "peer": true,
1099 | "dependencies": {
1100 | "fast-deep-equal": "^3.1.1",
1101 | "fast-json-stable-stringify": "^2.0.0",
1102 | "json-schema-traverse": "^0.4.1",
1103 | "uri-js": "^4.2.2"
1104 | },
1105 | "funding": {
1106 | "type": "github",
1107 | "url": "https://github.com/sponsors/epoberezkin"
1108 | }
1109 | },
1110 | "node_modules/ajv-keywords": {
1111 | "version": "3.5.2",
1112 | "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
1113 | "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
1114 | "dev": true,
1115 | "peer": true,
1116 | "peerDependencies": {
1117 | "ajv": "^6.9.1"
1118 | }
1119 | },
1120 | "node_modules/ansi-styles": {
1121 | "version": "4.3.0",
1122 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
1123 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
1124 | "dev": true,
1125 | "dependencies": {
1126 | "color-convert": "^2.0.1"
1127 | },
1128 | "engines": {
1129 | "node": ">=8"
1130 | },
1131 | "funding": {
1132 | "url": "https://github.com/chalk/ansi-styles?sponsor=1"
1133 | }
1134 | },
1135 | "node_modules/braces": {
1136 | "version": "3.0.2",
1137 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
1138 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
1139 | "dev": true,
1140 | "dependencies": {
1141 | "fill-range": "^7.0.1"
1142 | },
1143 | "engines": {
1144 | "node": ">=8"
1145 | }
1146 | },
1147 | "node_modules/browserslist": {
1148 | "version": "4.21.10",
1149 | "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
1150 | "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
1151 | "dev": true,
1152 | "funding": [
1153 | {
1154 | "type": "opencollective",
1155 | "url": "https://opencollective.com/browserslist"
1156 | },
1157 | {
1158 | "type": "tidelift",
1159 | "url": "https://tidelift.com/funding/github/npm/browserslist"
1160 | },
1161 | {
1162 | "type": "github",
1163 | "url": "https://github.com/sponsors/ai"
1164 | }
1165 | ],
1166 | "peer": true,
1167 | "dependencies": {
1168 | "caniuse-lite": "^1.0.30001517",
1169 | "electron-to-chromium": "^1.4.477",
1170 | "node-releases": "^2.0.13",
1171 | "update-browserslist-db": "^1.0.11"
1172 | },
1173 | "bin": {
1174 | "browserslist": "cli.js"
1175 | },
1176 | "engines": {
1177 | "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
1178 | }
1179 | },
1180 | "node_modules/buffer-from": {
1181 | "version": "1.1.2",
1182 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
1183 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
1184 | "dev": true
1185 | },
1186 | "node_modules/caniuse-lite": {
1187 | "version": "1.0.30001519",
1188 | "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001519.tgz",
1189 | "integrity": "sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg==",
1190 | "dev": true,
1191 | "funding": [
1192 | {
1193 | "type": "opencollective",
1194 | "url": "https://opencollective.com/browserslist"
1195 | },
1196 | {
1197 | "type": "tidelift",
1198 | "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
1199 | },
1200 | {
1201 | "type": "github",
1202 | "url": "https://github.com/sponsors/ai"
1203 | }
1204 | ],
1205 | "peer": true
1206 | },
1207 | "node_modules/chalk": {
1208 | "version": "4.1.2",
1209 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
1210 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
1211 | "dev": true,
1212 | "dependencies": {
1213 | "ansi-styles": "^4.1.0",
1214 | "supports-color": "^7.1.0"
1215 | },
1216 | "engines": {
1217 | "node": ">=10"
1218 | },
1219 | "funding": {
1220 | "url": "https://github.com/chalk/chalk?sponsor=1"
1221 | }
1222 | },
1223 | "node_modules/chrome-trace-event": {
1224 | "version": "1.0.3",
1225 | "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
1226 | "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==",
1227 | "dev": true,
1228 | "peer": true,
1229 | "engines": {
1230 | "node": ">=6.0"
1231 | }
1232 | },
1233 | "node_modules/color-convert": {
1234 | "version": "2.0.1",
1235 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
1236 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
1237 | "dev": true,
1238 | "dependencies": {
1239 | "color-name": "~1.1.4"
1240 | },
1241 | "engines": {
1242 | "node": ">=7.0.0"
1243 | }
1244 | },
1245 | "node_modules/color-name": {
1246 | "version": "1.1.4",
1247 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
1248 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
1249 | "dev": true
1250 | },
1251 | "node_modules/commander": {
1252 | "version": "2.20.3",
1253 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
1254 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
1255 | "dev": true,
1256 | "peer": true
1257 | },
1258 | "node_modules/electron-to-chromium": {
1259 | "version": "1.4.490",
1260 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.490.tgz",
1261 | "integrity": "sha512-6s7NVJz+sATdYnIwhdshx/N/9O6rvMxmhVoDSDFdj6iA45gHR8EQje70+RYsF4GeB+k0IeNSBnP7yG9ZXJFr7A==",
1262 | "dev": true,
1263 | "peer": true
1264 | },
1265 | "node_modules/enhanced-resolve": {
1266 | "version": "5.15.0",
1267 | "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
1268 | "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
1269 | "dev": true,
1270 | "dependencies": {
1271 | "graceful-fs": "^4.2.4",
1272 | "tapable": "^2.2.0"
1273 | },
1274 | "engines": {
1275 | "node": ">=10.13.0"
1276 | }
1277 | },
1278 | "node_modules/es-module-lexer": {
1279 | "version": "1.3.0",
1280 | "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.0.tgz",
1281 | "integrity": "sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==",
1282 | "dev": true,
1283 | "peer": true
1284 | },
1285 | "node_modules/esbuild": {
1286 | "version": "0.19.3",
1287 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.3.tgz",
1288 | "integrity": "sha512-UlJ1qUUA2jL2nNib1JTSkifQTcYTroFqRjwCFW4QYEKEsixXD5Tik9xML7zh2gTxkYTBKGHNH9y7txMwVyPbjw==",
1289 | "dev": true,
1290 | "hasInstallScript": true,
1291 | "bin": {
1292 | "esbuild": "bin/esbuild"
1293 | },
1294 | "engines": {
1295 | "node": ">=12"
1296 | },
1297 | "optionalDependencies": {
1298 | "@esbuild/android-arm": "0.19.3",
1299 | "@esbuild/android-arm64": "0.19.3",
1300 | "@esbuild/android-x64": "0.19.3",
1301 | "@esbuild/darwin-arm64": "0.19.3",
1302 | "@esbuild/darwin-x64": "0.19.3",
1303 | "@esbuild/freebsd-arm64": "0.19.3",
1304 | "@esbuild/freebsd-x64": "0.19.3",
1305 | "@esbuild/linux-arm": "0.19.3",
1306 | "@esbuild/linux-arm64": "0.19.3",
1307 | "@esbuild/linux-ia32": "0.19.3",
1308 | "@esbuild/linux-loong64": "0.19.3",
1309 | "@esbuild/linux-mips64el": "0.19.3",
1310 | "@esbuild/linux-ppc64": "0.19.3",
1311 | "@esbuild/linux-riscv64": "0.19.3",
1312 | "@esbuild/linux-s390x": "0.19.3",
1313 | "@esbuild/linux-x64": "0.19.3",
1314 | "@esbuild/netbsd-x64": "0.19.3",
1315 | "@esbuild/openbsd-x64": "0.19.3",
1316 | "@esbuild/sunos-x64": "0.19.3",
1317 | "@esbuild/win32-arm64": "0.19.3",
1318 | "@esbuild/win32-ia32": "0.19.3",
1319 | "@esbuild/win32-x64": "0.19.3"
1320 | }
1321 | },
1322 | "node_modules/escalade": {
1323 | "version": "3.1.1",
1324 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
1325 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
1326 | "dev": true,
1327 | "peer": true,
1328 | "engines": {
1329 | "node": ">=6"
1330 | }
1331 | },
1332 | "node_modules/eslint-scope": {
1333 | "version": "5.1.1",
1334 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
1335 | "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
1336 | "dev": true,
1337 | "peer": true,
1338 | "dependencies": {
1339 | "esrecurse": "^4.3.0",
1340 | "estraverse": "^4.1.1"
1341 | },
1342 | "engines": {
1343 | "node": ">=8.0.0"
1344 | }
1345 | },
1346 | "node_modules/esrecurse": {
1347 | "version": "4.3.0",
1348 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
1349 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
1350 | "dev": true,
1351 | "peer": true,
1352 | "dependencies": {
1353 | "estraverse": "^5.2.0"
1354 | },
1355 | "engines": {
1356 | "node": ">=4.0"
1357 | }
1358 | },
1359 | "node_modules/esrecurse/node_modules/estraverse": {
1360 | "version": "5.3.0",
1361 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
1362 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
1363 | "dev": true,
1364 | "peer": true,
1365 | "engines": {
1366 | "node": ">=4.0"
1367 | }
1368 | },
1369 | "node_modules/estraverse": {
1370 | "version": "4.3.0",
1371 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
1372 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
1373 | "dev": true,
1374 | "peer": true,
1375 | "engines": {
1376 | "node": ">=4.0"
1377 | }
1378 | },
1379 | "node_modules/events": {
1380 | "version": "3.3.0",
1381 | "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
1382 | "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
1383 | "dev": true,
1384 | "peer": true,
1385 | "engines": {
1386 | "node": ">=0.8.x"
1387 | }
1388 | },
1389 | "node_modules/fast-deep-equal": {
1390 | "version": "3.1.3",
1391 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
1392 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
1393 | "dev": true,
1394 | "peer": true
1395 | },
1396 | "node_modules/fast-json-stable-stringify": {
1397 | "version": "2.1.0",
1398 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
1399 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
1400 | "dev": true,
1401 | "peer": true
1402 | },
1403 | "node_modules/fill-range": {
1404 | "version": "7.0.1",
1405 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
1406 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
1407 | "dev": true,
1408 | "dependencies": {
1409 | "to-regex-range": "^5.0.1"
1410 | },
1411 | "engines": {
1412 | "node": ">=8"
1413 | }
1414 | },
1415 | "node_modules/fsevents": {
1416 | "version": "2.3.2",
1417 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
1418 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
1419 | "dev": true,
1420 | "hasInstallScript": true,
1421 | "optional": true,
1422 | "os": [
1423 | "darwin"
1424 | ],
1425 | "engines": {
1426 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
1427 | }
1428 | },
1429 | "node_modules/get-tsconfig": {
1430 | "version": "4.7.0",
1431 | "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.0.tgz",
1432 | "integrity": "sha512-pmjiZ7xtB8URYm74PlGJozDNyhvsVLUcpBa8DZBG3bWHwaHa9bPiRpiSfovw+fjhwONSCWKRyk+JQHEGZmMrzw==",
1433 | "dev": true,
1434 | "dependencies": {
1435 | "resolve-pkg-maps": "^1.0.0"
1436 | },
1437 | "funding": {
1438 | "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
1439 | }
1440 | },
1441 | "node_modules/glob-to-regexp": {
1442 | "version": "0.4.1",
1443 | "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
1444 | "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
1445 | "dev": true,
1446 | "peer": true
1447 | },
1448 | "node_modules/graceful-fs": {
1449 | "version": "4.2.11",
1450 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
1451 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
1452 | "dev": true
1453 | },
1454 | "node_modules/has-flag": {
1455 | "version": "4.0.0",
1456 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
1457 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
1458 | "dev": true,
1459 | "engines": {
1460 | "node": ">=8"
1461 | }
1462 | },
1463 | "node_modules/is-number": {
1464 | "version": "7.0.0",
1465 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
1466 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
1467 | "dev": true,
1468 | "engines": {
1469 | "node": ">=0.12.0"
1470 | }
1471 | },
1472 | "node_modules/jest-worker": {
1473 | "version": "27.5.1",
1474 | "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
1475 | "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
1476 | "dev": true,
1477 | "peer": true,
1478 | "dependencies": {
1479 | "@types/node": "*",
1480 | "merge-stream": "^2.0.0",
1481 | "supports-color": "^8.0.0"
1482 | },
1483 | "engines": {
1484 | "node": ">= 10.13.0"
1485 | }
1486 | },
1487 | "node_modules/jest-worker/node_modules/supports-color": {
1488 | "version": "8.1.1",
1489 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
1490 | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
1491 | "dev": true,
1492 | "peer": true,
1493 | "dependencies": {
1494 | "has-flag": "^4.0.0"
1495 | },
1496 | "engines": {
1497 | "node": ">=10"
1498 | },
1499 | "funding": {
1500 | "url": "https://github.com/chalk/supports-color?sponsor=1"
1501 | }
1502 | },
1503 | "node_modules/json-parse-even-better-errors": {
1504 | "version": "2.3.1",
1505 | "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
1506 | "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
1507 | "dev": true,
1508 | "peer": true
1509 | },
1510 | "node_modules/json-schema-traverse": {
1511 | "version": "0.4.1",
1512 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
1513 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
1514 | "dev": true,
1515 | "peer": true
1516 | },
1517 | "node_modules/loader-runner": {
1518 | "version": "4.3.0",
1519 | "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
1520 | "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
1521 | "dev": true,
1522 | "peer": true,
1523 | "engines": {
1524 | "node": ">=6.11.5"
1525 | }
1526 | },
1527 | "node_modules/lru-cache": {
1528 | "version": "6.0.0",
1529 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
1530 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
1531 | "dev": true,
1532 | "dependencies": {
1533 | "yallist": "^4.0.0"
1534 | },
1535 | "engines": {
1536 | "node": ">=10"
1537 | }
1538 | },
1539 | "node_modules/merge-stream": {
1540 | "version": "2.0.0",
1541 | "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
1542 | "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
1543 | "dev": true,
1544 | "peer": true
1545 | },
1546 | "node_modules/micromatch": {
1547 | "version": "4.0.5",
1548 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
1549 | "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
1550 | "dev": true,
1551 | "dependencies": {
1552 | "braces": "^3.0.2",
1553 | "picomatch": "^2.3.1"
1554 | },
1555 | "engines": {
1556 | "node": ">=8.6"
1557 | }
1558 | },
1559 | "node_modules/mime-db": {
1560 | "version": "1.52.0",
1561 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
1562 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
1563 | "dev": true,
1564 | "peer": true,
1565 | "engines": {
1566 | "node": ">= 0.6"
1567 | }
1568 | },
1569 | "node_modules/mime-types": {
1570 | "version": "2.1.35",
1571 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
1572 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
1573 | "dev": true,
1574 | "peer": true,
1575 | "dependencies": {
1576 | "mime-db": "1.52.0"
1577 | },
1578 | "engines": {
1579 | "node": ">= 0.6"
1580 | }
1581 | },
1582 | "node_modules/neo-async": {
1583 | "version": "2.6.2",
1584 | "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
1585 | "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
1586 | "dev": true,
1587 | "peer": true
1588 | },
1589 | "node_modules/node-releases": {
1590 | "version": "2.0.13",
1591 | "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
1592 | "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
1593 | "dev": true,
1594 | "peer": true
1595 | },
1596 | "node_modules/picocolors": {
1597 | "version": "1.0.0",
1598 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
1599 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
1600 | "dev": true,
1601 | "peer": true
1602 | },
1603 | "node_modules/picomatch": {
1604 | "version": "2.3.1",
1605 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
1606 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
1607 | "dev": true,
1608 | "engines": {
1609 | "node": ">=8.6"
1610 | },
1611 | "funding": {
1612 | "url": "https://github.com/sponsors/jonschlinkert"
1613 | }
1614 | },
1615 | "node_modules/punycode": {
1616 | "version": "2.3.0",
1617 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
1618 | "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
1619 | "dev": true,
1620 | "peer": true,
1621 | "engines": {
1622 | "node": ">=6"
1623 | }
1624 | },
1625 | "node_modules/randombytes": {
1626 | "version": "2.1.0",
1627 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
1628 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
1629 | "dev": true,
1630 | "peer": true,
1631 | "dependencies": {
1632 | "safe-buffer": "^5.1.0"
1633 | }
1634 | },
1635 | "node_modules/resolve-pkg-maps": {
1636 | "version": "1.0.0",
1637 | "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
1638 | "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
1639 | "dev": true,
1640 | "funding": {
1641 | "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
1642 | }
1643 | },
1644 | "node_modules/safe-buffer": {
1645 | "version": "5.2.1",
1646 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
1647 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
1648 | "dev": true,
1649 | "funding": [
1650 | {
1651 | "type": "github",
1652 | "url": "https://github.com/sponsors/feross"
1653 | },
1654 | {
1655 | "type": "patreon",
1656 | "url": "https://www.patreon.com/feross"
1657 | },
1658 | {
1659 | "type": "consulting",
1660 | "url": "https://feross.org/support"
1661 | }
1662 | ],
1663 | "peer": true
1664 | },
1665 | "node_modules/schema-utils": {
1666 | "version": "3.3.0",
1667 | "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
1668 | "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
1669 | "dev": true,
1670 | "peer": true,
1671 | "dependencies": {
1672 | "@types/json-schema": "^7.0.8",
1673 | "ajv": "^6.12.5",
1674 | "ajv-keywords": "^3.5.2"
1675 | },
1676 | "engines": {
1677 | "node": ">= 10.13.0"
1678 | },
1679 | "funding": {
1680 | "type": "opencollective",
1681 | "url": "https://opencollective.com/webpack"
1682 | }
1683 | },
1684 | "node_modules/semver": {
1685 | "version": "7.5.4",
1686 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
1687 | "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
1688 | "dev": true,
1689 | "dependencies": {
1690 | "lru-cache": "^6.0.0"
1691 | },
1692 | "bin": {
1693 | "semver": "bin/semver.js"
1694 | },
1695 | "engines": {
1696 | "node": ">=10"
1697 | }
1698 | },
1699 | "node_modules/serialize-javascript": {
1700 | "version": "6.0.1",
1701 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz",
1702 | "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==",
1703 | "dev": true,
1704 | "peer": true,
1705 | "dependencies": {
1706 | "randombytes": "^2.1.0"
1707 | }
1708 | },
1709 | "node_modules/source-map": {
1710 | "version": "0.6.1",
1711 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
1712 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
1713 | "dev": true,
1714 | "engines": {
1715 | "node": ">=0.10.0"
1716 | }
1717 | },
1718 | "node_modules/source-map-support": {
1719 | "version": "0.5.21",
1720 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
1721 | "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
1722 | "dev": true,
1723 | "dependencies": {
1724 | "buffer-from": "^1.0.0",
1725 | "source-map": "^0.6.0"
1726 | }
1727 | },
1728 | "node_modules/supports-color": {
1729 | "version": "7.2.0",
1730 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
1731 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
1732 | "dev": true,
1733 | "dependencies": {
1734 | "has-flag": "^4.0.0"
1735 | },
1736 | "engines": {
1737 | "node": ">=8"
1738 | }
1739 | },
1740 | "node_modules/tapable": {
1741 | "version": "2.2.1",
1742 | "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
1743 | "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
1744 | "dev": true,
1745 | "engines": {
1746 | "node": ">=6"
1747 | }
1748 | },
1749 | "node_modules/terser": {
1750 | "version": "5.19.2",
1751 | "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.2.tgz",
1752 | "integrity": "sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==",
1753 | "dev": true,
1754 | "peer": true,
1755 | "dependencies": {
1756 | "@jridgewell/source-map": "^0.3.3",
1757 | "acorn": "^8.8.2",
1758 | "commander": "^2.20.0",
1759 | "source-map-support": "~0.5.20"
1760 | },
1761 | "bin": {
1762 | "terser": "bin/terser"
1763 | },
1764 | "engines": {
1765 | "node": ">=10"
1766 | }
1767 | },
1768 | "node_modules/terser-webpack-plugin": {
1769 | "version": "5.3.9",
1770 | "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz",
1771 | "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==",
1772 | "dev": true,
1773 | "peer": true,
1774 | "dependencies": {
1775 | "@jridgewell/trace-mapping": "^0.3.17",
1776 | "jest-worker": "^27.4.5",
1777 | "schema-utils": "^3.1.1",
1778 | "serialize-javascript": "^6.0.1",
1779 | "terser": "^5.16.8"
1780 | },
1781 | "engines": {
1782 | "node": ">= 10.13.0"
1783 | },
1784 | "funding": {
1785 | "type": "opencollective",
1786 | "url": "https://opencollective.com/webpack"
1787 | },
1788 | "peerDependencies": {
1789 | "webpack": "^5.1.0"
1790 | },
1791 | "peerDependenciesMeta": {
1792 | "@swc/core": {
1793 | "optional": true
1794 | },
1795 | "esbuild": {
1796 | "optional": true
1797 | },
1798 | "uglify-js": {
1799 | "optional": true
1800 | }
1801 | }
1802 | },
1803 | "node_modules/to-regex-range": {
1804 | "version": "5.0.1",
1805 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
1806 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
1807 | "dev": true,
1808 | "dependencies": {
1809 | "is-number": "^7.0.0"
1810 | },
1811 | "engines": {
1812 | "node": ">=8.0"
1813 | }
1814 | },
1815 | "node_modules/ts-loader": {
1816 | "version": "9.4.4",
1817 | "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.4.tgz",
1818 | "integrity": "sha512-MLukxDHBl8OJ5Dk3y69IsKVFRA/6MwzEqBgh+OXMPB/OD01KQuWPFd1WAQP8a5PeSCAxfnkhiuWqfmFJzJQt9w==",
1819 | "dev": true,
1820 | "dependencies": {
1821 | "chalk": "^4.1.0",
1822 | "enhanced-resolve": "^5.0.0",
1823 | "micromatch": "^4.0.0",
1824 | "semver": "^7.3.4"
1825 | },
1826 | "engines": {
1827 | "node": ">=12.0.0"
1828 | },
1829 | "peerDependencies": {
1830 | "typescript": "*",
1831 | "webpack": "^5.0.0"
1832 | }
1833 | },
1834 | "node_modules/tsx": {
1835 | "version": "3.12.7",
1836 | "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.12.7.tgz",
1837 | "integrity": "sha512-C2Ip+jPmqKd1GWVQDvz/Eyc6QJbGfE7NrR3fx5BpEHMZsEHoIxHL1j+lKdGobr8ovEyqeNkPLSKp6SCSOt7gmw==",
1838 | "dev": true,
1839 | "dependencies": {
1840 | "@esbuild-kit/cjs-loader": "^2.4.2",
1841 | "@esbuild-kit/core-utils": "^3.0.0",
1842 | "@esbuild-kit/esm-loader": "^2.5.5"
1843 | },
1844 | "bin": {
1845 | "tsx": "dist/cli.js"
1846 | },
1847 | "optionalDependencies": {
1848 | "fsevents": "~2.3.2"
1849 | }
1850 | },
1851 | "node_modules/typescript": {
1852 | "version": "5.1.6",
1853 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
1854 | "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==",
1855 | "dev": true,
1856 | "bin": {
1857 | "tsc": "bin/tsc",
1858 | "tsserver": "bin/tsserver"
1859 | },
1860 | "engines": {
1861 | "node": ">=14.17"
1862 | }
1863 | },
1864 | "node_modules/update-browserslist-db": {
1865 | "version": "1.0.11",
1866 | "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz",
1867 | "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==",
1868 | "dev": true,
1869 | "funding": [
1870 | {
1871 | "type": "opencollective",
1872 | "url": "https://opencollective.com/browserslist"
1873 | },
1874 | {
1875 | "type": "tidelift",
1876 | "url": "https://tidelift.com/funding/github/npm/browserslist"
1877 | },
1878 | {
1879 | "type": "github",
1880 | "url": "https://github.com/sponsors/ai"
1881 | }
1882 | ],
1883 | "peer": true,
1884 | "dependencies": {
1885 | "escalade": "^3.1.1",
1886 | "picocolors": "^1.0.0"
1887 | },
1888 | "bin": {
1889 | "update-browserslist-db": "cli.js"
1890 | },
1891 | "peerDependencies": {
1892 | "browserslist": ">= 4.21.0"
1893 | }
1894 | },
1895 | "node_modules/uri-js": {
1896 | "version": "4.4.1",
1897 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
1898 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
1899 | "dev": true,
1900 | "peer": true,
1901 | "dependencies": {
1902 | "punycode": "^2.1.0"
1903 | }
1904 | },
1905 | "node_modules/watchpack": {
1906 | "version": "2.4.0",
1907 | "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
1908 | "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
1909 | "dev": true,
1910 | "peer": true,
1911 | "dependencies": {
1912 | "glob-to-regexp": "^0.4.1",
1913 | "graceful-fs": "^4.1.2"
1914 | },
1915 | "engines": {
1916 | "node": ">=10.13.0"
1917 | }
1918 | },
1919 | "node_modules/webpack": {
1920 | "version": "5.88.2",
1921 | "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz",
1922 | "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==",
1923 | "dev": true,
1924 | "peer": true,
1925 | "dependencies": {
1926 | "@types/eslint-scope": "^3.7.3",
1927 | "@types/estree": "^1.0.0",
1928 | "@webassemblyjs/ast": "^1.11.5",
1929 | "@webassemblyjs/wasm-edit": "^1.11.5",
1930 | "@webassemblyjs/wasm-parser": "^1.11.5",
1931 | "acorn": "^8.7.1",
1932 | "acorn-import-assertions": "^1.9.0",
1933 | "browserslist": "^4.14.5",
1934 | "chrome-trace-event": "^1.0.2",
1935 | "enhanced-resolve": "^5.15.0",
1936 | "es-module-lexer": "^1.2.1",
1937 | "eslint-scope": "5.1.1",
1938 | "events": "^3.2.0",
1939 | "glob-to-regexp": "^0.4.1",
1940 | "graceful-fs": "^4.2.9",
1941 | "json-parse-even-better-errors": "^2.3.1",
1942 | "loader-runner": "^4.2.0",
1943 | "mime-types": "^2.1.27",
1944 | "neo-async": "^2.6.2",
1945 | "schema-utils": "^3.2.0",
1946 | "tapable": "^2.1.1",
1947 | "terser-webpack-plugin": "^5.3.7",
1948 | "watchpack": "^2.4.0",
1949 | "webpack-sources": "^3.2.3"
1950 | },
1951 | "bin": {
1952 | "webpack": "bin/webpack.js"
1953 | },
1954 | "engines": {
1955 | "node": ">=10.13.0"
1956 | },
1957 | "funding": {
1958 | "type": "opencollective",
1959 | "url": "https://opencollective.com/webpack"
1960 | },
1961 | "peerDependenciesMeta": {
1962 | "webpack-cli": {
1963 | "optional": true
1964 | }
1965 | }
1966 | },
1967 | "node_modules/webpack-sources": {
1968 | "version": "3.2.3",
1969 | "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
1970 | "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
1971 | "dev": true,
1972 | "peer": true,
1973 | "engines": {
1974 | "node": ">=10.13.0"
1975 | }
1976 | },
1977 | "node_modules/yallist": {
1978 | "version": "4.0.0",
1979 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
1980 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
1981 | "dev": true
1982 | }
1983 | },
1984 | "version": "1.1.2"
1985 | }
1986 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "text-graph.js",
3 | "version": "1.1.2",
4 | "author": "DrA1ex",
5 | "description": "A versatile JavaScript library for creating ASCII charts in the terminal and browser console",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/DrA1ex/text-graph.js.git"
9 | },
10 | "homepage": "https://github.com/DrA1ex/text-graph.js",
11 | "keywords": [
12 | "ascii-chart",
13 | "terminal-chart",
14 | "console-chart",
15 | "browser-chart",
16 | "chart-library",
17 | "multi-series-chart",
18 | "chart-dashboard",
19 | "text-graph",
20 | "data-visualization",
21 | "javascript-graph",
22 | "ascii-visualization",
23 | "dashboard-library",
24 | "text-based-chart",
25 | "text-based-visualization"
26 | ],
27 | "license": "BSD-3-Clause",
28 | "scripts": {
29 | "bundle_esm": "esbuild src/index.ts --bundle --format=esm --outdir=./lib --out-extension:.js=.mjs",
30 | "bundle_cjs": "esbuild src/index.ts --bundle --format=cjs --outdir=./lib --out-extension:.js=.js",
31 | "build": "rm -rf ./lib/ && tsc --project tsconfig.lib.json && npm run bundle_esm && npm run bundle_cjs"
32 | },
33 | "devDependencies": {
34 | "esbuild": "^0.19.3",
35 | "ts-loader": "^9.4.4",
36 | "tsx": "^3.12.7",
37 | "typescript": "^5.1.6"
38 | },
39 | "main": "./lib/index.js",
40 | "module": "./lib/index.mjs",
41 | "types": "./lib/index.d.ts",
42 | "exports": {
43 | ".": {
44 | "require": "./lib/index.js",
45 | "import": "./lib/index.mjs",
46 | "types": "./lib/index.d.ts"
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/axis.ts:
--------------------------------------------------------------------------------
1 | import {PlotAxisScale} from "./enum";
2 | import * as Utils from "./utils";
3 |
4 | export class Axis {
5 | readonly labels: number[];
6 |
7 | constructor(public min: number,
8 | public max: number,
9 | public readonly size: number,
10 | public readonly scale: PlotAxisScale,
11 | ) {
12 | if (min > max) throw new Error("Incorrect range: min should be less or equals to max")
13 | if (this.size <= 1) throw new Error("Size should be >= 2");
14 |
15 | switch (this.scale) {
16 | case PlotAxisScale.log:
17 | this.labels = Array.from(Utils.logDistribution(this.min, this.max, this.size));
18 | break;
19 |
20 | case PlotAxisScale.logInverted:
21 | this.labels = Array.from(Utils.invertedLogDistribution(this.min, this.max, this.size));
22 | break;
23 |
24 | default:
25 | this.labels = Array.from(Utils.linearDistribution(this.min, this.max, this.size));
26 | }
27 | }
28 |
29 | getPosition(value: number) {
30 | const index = Utils.findClosestIndexSorted(this.labels, value);
31 | return this.size - 1 - index;
32 | }
33 | }
--------------------------------------------------------------------------------
/src/enum.ts:
--------------------------------------------------------------------------------
1 | import * as Utils from "./utils"
2 |
3 | export enum LabelPositionFlags {
4 | top = 1 << 1,
5 | bottom = 1 << 2,
6 | left = 1 << 5,
7 | right = 1 << 6,
8 |
9 | top_left = top | left,
10 | top_right = top | right,
11 | bottom_left = bottom | left,
12 | bottom_right = bottom | right,
13 | }
14 |
15 | export enum Color {
16 | red = "\x1b[31m",
17 | green = "\x1b[32m",
18 | yellow = "\x1b[33m",
19 | blue = "\x1b[34m",
20 | magenta = "\x1b[35m",
21 | cyan = "\x1b[36m",
22 | lightgray = "\x1b[37m",
23 | default = "\x1b[39m",
24 |
25 | white = "\x1b[97m",
26 | black = "\x1b[30m",
27 | reset = "\x1b[0m",
28 | }
29 |
30 | export enum BackgroundColor {
31 | black = "\x1b[40m",
32 | red = "\x1b[41m",
33 | green = "\x1b[42m",
34 | yellow = "\x1b[43m",
35 | blue = "\x1b[44m",
36 | magenta = "\x1b[45m",
37 | cyan = "\x1b[46m",
38 | lightgray = "\x1b[47m",
39 | default = "\x1b[49m",
40 | }
41 |
42 | export enum PlotSeriesOverflow {
43 | linearScale,
44 | logScale,
45 | clamp,
46 | }
47 |
48 | export enum PlotAxisScale {
49 | linear,
50 | log,
51 | logInverted
52 | }
53 |
54 | export const PlotSeriesAggregationFn = {
55 | mean: Utils.aggregateAverage,
56 | min: Utils.aggregateMin,
57 | max: Utils.aggregateMax,
58 | skip: Utils.aggregateSkip,
59 | } as const;
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import {Plot} from "./plot";
2 | import {MultiPlotChart} from "./multi-plot";
3 |
4 | export default {
5 | Plot,
6 | MultiPlotChart
7 | }
8 |
9 | export {Plot, MultiPlotChart}
10 | export {
11 | Color, BackgroundColor, PlotAxisScale, PlotSeriesOverflow, LabelPositionFlags, PlotSeriesAggregationFn
12 | } from "./enum"
--------------------------------------------------------------------------------
/src/label.ts:
--------------------------------------------------------------------------------
1 | import {BackgroundColor, Color, LabelPositionFlags} from "./enum";
2 |
3 | export const LabelDefaults = {
4 | align: LabelPositionFlags.top,
5 | foregroundColor: Color.black,
6 | backgroundColor: BackgroundColor.lightgray,
7 | spacing: 1,
8 | minWidth: 4
9 | }
10 |
11 | export class Label {
12 | public foregroundColor = LabelDefaults.foregroundColor;
13 | public backgroundColor = LabelDefaults.backgroundColor;
14 |
15 | constructor(
16 | public readonly label: string,
17 | public readonly width: number,
18 | public readonly height: number,
19 | public readonly boundary: number = 0,
20 | public readonly align: LabelPositionFlags = LabelDefaults.align,
21 | public readonly spacing = LabelDefaults.spacing,
22 | ) {
23 | }
24 |
25 | public draw(screen: string[][], xOffset: number, yOffset: number) {
26 | const maxWidth = this.width - xOffset;
27 | if (!this.label || maxWidth <= LabelDefaults.minWidth) return;
28 |
29 | let label = this._clipLabel(this.label, maxWidth, this.boundary);
30 | if (label.length < maxWidth) {
31 | const spacing = Math.min(this.spacing, Math.floor(maxWidth - label.length) / 2);
32 |
33 | if (spacing) {
34 | label = " ".repeat(spacing) + label + " ".repeat(spacing);
35 | }
36 | }
37 |
38 | let x;
39 | if (this.align & LabelPositionFlags.left) {
40 | x = 0
41 | } else if (this.align & LabelPositionFlags.right) {
42 | x = this.width - label.length - 1;
43 | } else {
44 | x = xOffset + Math.round(maxWidth / 2 - label.length / 2)
45 | }
46 |
47 | let y = yOffset;
48 | if (this.align & LabelPositionFlags.bottom) {
49 | y = this.height - 1 - yOffset;
50 | }
51 |
52 | for (let i = 0; i < label.length; i++) {
53 | screen[y][x + i] = this.backgroundColor + this.foregroundColor + label[i] + Color.reset;
54 | }
55 | }
56 |
57 | private _clipLabel(label: string, maxLength: number, boundary: number): string {
58 | if (label.length > maxLength) {
59 | return label.slice(0, maxLength - boundary - 1) + "…";
60 | }
61 |
62 | return label
63 | }
64 | }
--------------------------------------------------------------------------------
/src/multi-plot.ts:
--------------------------------------------------------------------------------
1 | import {BackgroundColor, Color, LabelPositionFlags} from "./enum";
2 | import {Plot, PlotOptions, PlotSeriesConfig} from "./plot";
3 | import {Label, LabelDefaults} from "./label";
4 |
5 | type ChartPlotConfig = {
6 | xOffset: number,
7 | yOffset: number,
8 | width: number,
9 | height: number,
10 | };
11 |
12 | type MultiPlotOptionsT = {
13 | title: string,
14 | titlePosition: LabelPositionFlags,
15 | titleForeground: Color,
16 | titleBackground: BackgroundColor,
17 | titleBoundary: number,
18 | titleSpacing: number,
19 | }
20 |
21 | const MultiPlotOptionsDefaults = {
22 | title: "",
23 | titlePosition: LabelDefaults.align,
24 | titleForeground: LabelDefaults.foregroundColor,
25 | titleBackground: LabelDefaults.backgroundColor,
26 | titleBoundary: 1,
27 | titleSpacing: LabelDefaults.spacing,
28 | }
29 |
30 | export class MultiPlotChart {
31 | get title(): string {
32 | return this._title;
33 | }
34 |
35 | set title(value: string) {
36 | const needDrawTitleChanged = !!value !== !!this._title;
37 | this._title = value;
38 |
39 | this._updateScreen();
40 | }
41 |
42 | public width: number = 0;
43 | public height: number = 0;
44 |
45 | private _title: string;
46 | public titlePosition: LabelPositionFlags;
47 | public titleForeground: Color;
48 | public titleBackground: BackgroundColor;
49 | public titleBoundary: number;
50 | public titleSpacing: number;
51 |
52 | public readonly plots: Plot[] = [];
53 | private readonly configs = new Map();
54 |
55 | public screen!: string[][];
56 |
57 | constructor(options: Partial = {}) {
58 | const opts = {...MultiPlotOptionsDefaults, ...options};
59 |
60 | this._title = opts.title;
61 | this.titlePosition = opts.titlePosition;
62 | this.titleForeground = opts.titleForeground;
63 | this.titleBackground = opts.titleBackground;
64 | this.titleBoundary = opts.titleBoundary;
65 | this.titleSpacing = opts.titleSpacing;
66 | }
67 |
68 | public addPlot(config: ChartPlotConfig, options?: Partial): number {
69 | const plot = new Plot(config.width, config.height, options);
70 | this.plots.push(plot);
71 | this.configs.set(plot, config);
72 |
73 | this._updateScreen();
74 |
75 | return this.plots.length - 1;
76 | }
77 |
78 | public addPlotSeries(plotId: number, config: Partial): number {
79 | this._assertChartId(plotId);
80 |
81 | return this.plots[plotId].addSeries(config);
82 | }
83 |
84 | public addSeriesEntry(plotId: number, seriesId: number, entry: number) {
85 | this._assertChartId(plotId);
86 |
87 | this.plots[plotId].addSeriesEntry(seriesId, entry);
88 | }
89 |
90 | public redraw() {
91 | if (this.title) {
92 | const titleLabel = new Label(
93 | this.title, this.width, this.height, 0, this.titlePosition, this.titleSpacing
94 | );
95 |
96 | titleLabel.foregroundColor = this.titleForeground;
97 | titleLabel.backgroundColor = this.titleBackground;
98 | titleLabel.draw(this.screen, 0, 0);
99 | }
100 |
101 | const xGlobalOffset = 0;
102 | const yGlobalOffset = this.title && this.titlePosition & LabelPositionFlags.top ? this.titleBoundary : 0;
103 |
104 | for (const plot of this.plots) {
105 | this._drawPlot(plot, xGlobalOffset, yGlobalOffset);
106 | }
107 | }
108 |
109 | public paint(): string {
110 | this.redraw();
111 |
112 | return this.screen.map(row => row.join("")).join("\n") + Color.reset;
113 | }
114 |
115 | private _assertChartId(id: number) {
116 | if (id >= this.plots.length) {
117 | throw new Error("Wrong chart id");
118 | }
119 | }
120 |
121 | private _updateScreen() {
122 | let width = 0, height = 0;
123 | for (const conf of this.configs.values()) {
124 | width = Math.max(width, conf.xOffset + conf.width);
125 | height = Math.max(height, conf.yOffset + conf.height);
126 | }
127 |
128 | if (this.title) {
129 | height += this.titleBoundary;
130 | }
131 |
132 | this.width = width;
133 | this.height = height;
134 | this.screen = new Array(height);
135 | for (let i = 0; i < height; i++) {
136 | this.screen[i] = new Array(width).fill(Plot.SpaceSymbol);
137 | }
138 | }
139 |
140 | private _drawPlot(plot: Plot, xGlobalOffset: number, yGlobalOffset: number) {
141 | const config = this.configs.get(plot)!;
142 | const {xOffset, yOffset} = config;
143 |
144 | plot.redraw();
145 | for (let y = 0; y < plot.screen.length; y++) {
146 | const row = plot.screen[y];
147 | for (let x = 0; x < row.length; x++) {
148 | this.screen[y + yOffset + yGlobalOffset][x + xOffset + xGlobalOffset] = row[x];
149 | }
150 | }
151 | }
152 | }
--------------------------------------------------------------------------------
/src/plot.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Color,
3 | PlotAxisScale,
4 | PlotSeriesAggregationFn,
5 | PlotSeriesOverflow,
6 | LabelPositionFlags, BackgroundColor
7 | } from "./enum";
8 | import {Axis} from "./axis";
9 | import * as Utils from "./utils"
10 | import {Label, LabelDefaults} from "./label";
11 |
12 | enum States {
13 | straight = 0,
14 | up = 1,
15 | down = 2
16 | }
17 |
18 |
19 | export type PlotOptions = {
20 | showAxis: boolean,
21 | horizontalBoundary: number
22 | verticalBoundary: number
23 | title: string,
24 | titlePosition: LabelPositionFlags,
25 | titleForeground: Color,
26 | titleBackground: BackgroundColor,
27 | titleSpacing: number,
28 | axisScale: PlotAxisScale,
29 | aggregation: Utils.AggregationFn,
30 | axisLabelsFraction: number,
31 | zoom: boolean,
32 | }
33 |
34 | export type PlotStaticOptions = {
35 | width: number,
36 | height: number
37 | } & PlotOptions;
38 |
39 | export const PlotCtorDefaultOptions = {
40 | width: 80,
41 | height: 10,
42 | showAxis: true,
43 | axisScale: PlotAxisScale.linear,
44 | title: "",
45 | titlePosition: LabelDefaults.align,
46 | titleForeground: LabelDefaults.foregroundColor,
47 | titleBackground: LabelDefaults.backgroundColor,
48 | titleSpacing: LabelDefaults.spacing,
49 | horizontalBoundary: 0,
50 | axisLabelsFraction: 2,
51 | zoom: false
52 | }
53 |
54 |
55 | export type PlotSeriesConfig = {
56 | color: Color,
57 | overflow: PlotSeriesOverflow
58 | }
59 |
60 | const PlotSeriesDefaults: PlotSeriesConfig = {
61 | color: Color.default,
62 | overflow: PlotSeriesOverflow.linearScale
63 | }
64 |
65 | const PlotDefaultAggregation = {
66 | [PlotAxisScale.linear]: PlotSeriesAggregationFn.mean,
67 | [PlotAxisScale.log]: PlotSeriesAggregationFn.max,
68 | [PlotAxisScale.logInverted]: PlotSeriesAggregationFn.min,
69 | } as { [key in PlotAxisScale]: Utils.AggregationFn }
70 |
71 | export class Plot {
72 | static readonly AxisSymbol = "┼"
73 | static readonly SpaceSymbol = " ";
74 |
75 | static readonly ChartHorizontal = ["─", "╯", "╮",];
76 | static readonly ChartVertical = ["│", "╭", "╰",];
77 |
78 | public showAxis: boolean;
79 | public aggregationFn: Utils.AggregationFn;
80 | public axisScale: PlotAxisScale;
81 | public horizontalBoundary: number;
82 | public verticalBoundary: number;
83 | public axisLabelsFraction: number;
84 | public title: string;
85 | public titlePosition: LabelPositionFlags;
86 | public titleForeground: Color;
87 | public titleBackground: BackgroundColor;
88 | public titleSpacing: number;
89 | public zoom: boolean;
90 |
91 | public readonly width;
92 | public readonly height;
93 |
94 | public readonly screen!: string[][];
95 |
96 | private readonly series: number[][] = [];
97 | readonly seriesConfigs: PlotSeriesConfig[] = [];
98 |
99 | constructor(
100 | width = PlotCtorDefaultOptions.width, height = PlotCtorDefaultOptions.height, {
101 | showAxis = PlotCtorDefaultOptions.showAxis,
102 | axisScale = PlotCtorDefaultOptions.axisScale,
103 | aggregation = PlotDefaultAggregation[axisScale] ?? PlotSeriesAggregationFn.skip,
104 | title = PlotCtorDefaultOptions.title,
105 | titlePosition = PlotCtorDefaultOptions.titlePosition,
106 | titleForeground = PlotCtorDefaultOptions.titleForeground,
107 | titleBackground = PlotCtorDefaultOptions.titleBackground,
108 | titleSpacing = PlotCtorDefaultOptions.titleSpacing,
109 | horizontalBoundary = PlotCtorDefaultOptions.horizontalBoundary,
110 | verticalBoundary = title ? 1 : 0,
111 | axisLabelsFraction = PlotCtorDefaultOptions.axisLabelsFraction,
112 | zoom = PlotCtorDefaultOptions.zoom,
113 | }: Partial = {}
114 | ) {
115 | this.width = width;
116 | this.height = height;
117 |
118 | this.showAxis = showAxis;
119 | this.axisScale = axisScale;
120 | this.aggregationFn = aggregation;
121 | this.zoom = zoom;
122 |
123 | this.title = title;
124 | this.titlePosition = titlePosition;
125 | this.titleForeground = titleForeground;
126 | this.titleBackground = titleBackground;
127 | this.titleSpacing = titleSpacing;
128 |
129 | this.horizontalBoundary = horizontalBoundary;
130 | this.verticalBoundary = verticalBoundary;
131 | this.axisLabelsFraction = axisLabelsFraction;
132 |
133 | this.screen = new Array(this.height);
134 | for (let i = 0; i < this.height; i++) {
135 | this.screen[i] = new Array(this.width).fill(Plot.SpaceSymbol);
136 | }
137 | }
138 |
139 | static plot(
140 | data: number[], plotOptions?: Partial,
141 | seriesOptions: Partial = {}
142 | ): string {
143 | const opts = {...PlotCtorDefaultOptions, ...plotOptions}
144 | const p = new Plot(opts.width, opts.height, opts);
145 |
146 | p.addSeries(seriesOptions);
147 | p.addSeriesRange(0, data);
148 |
149 | return p.paint();
150 | }
151 |
152 | public addSeries(options: Partial = {}) {
153 | this.series.push([])
154 | this.seriesConfigs.push({...PlotSeriesDefaults, ...options});
155 |
156 | return this.series.length - 1;
157 | }
158 |
159 | public addSeriesEntry(seriesIndex: number, value: number) {
160 | if (seriesIndex >= this.series.length) throw new Error("Wrong series index");
161 | this.series[seriesIndex].push(value);
162 | }
163 |
164 | public addSeriesRange(seriesIndex: number, data: number[]) {
165 | if (seriesIndex >= this.series.length) throw new Error("Wrong series index");
166 | this.series[seriesIndex].push(...data);
167 | }
168 |
169 | public redraw() {
170 | this._clear();
171 |
172 | const size = Math.max(2, this.height - this.verticalBoundary * 2);
173 | let [min, max] = Utils.minMax2d(this.series);
174 | const axis = new Axis(min, max, size, this.axisScale);
175 |
176 | const yOffset = (this.height - size) / 2;
177 | let xOffset = 0;
178 | if (this.showAxis) {
179 | const labelPadding = this._drawAxis(yOffset, axis.labels);
180 | xOffset = labelPadding + 2;
181 | }
182 |
183 | const maxSeriesLength = this.width - xOffset - this.horizontalBoundary * 2 + 1;
184 | for (let i = 0; i < this.series.length; i++) {
185 | if (this.series[i].length <= 1) continue;
186 |
187 | const {color, overflow} = this.seriesConfigs[i];
188 | const seriesData = this.zoom ? Utils.zoomData(this.series[i], maxSeriesLength) : this.series[i];
189 | const data = this._handleOverflow(seriesData, overflow, maxSeriesLength);
190 |
191 | let lastState = States.straight;
192 | let lastY = yOffset + axis.getPosition(data[0]);
193 | let x = xOffset + this.horizontalBoundary;
194 |
195 | for (let j = 1; j < data.length; j++) {
196 | if (!Number.isFinite(data[j])) break;
197 |
198 | const y = yOffset + axis.getPosition(data[j]);
199 | const state = y === lastY ? States.straight
200 | : y < lastY ? States.up : States.down;
201 |
202 | if (lastState === States.straight) {
203 | this.screen[lastY][x++] = color + Plot.ChartHorizontal[lastState];
204 | this.screen[lastY][x] = color + Plot.ChartHorizontal[state];
205 | } else {
206 | this.screen[lastY][x++] = color + Plot.ChartVertical[lastState];
207 |
208 | if (state === States.straight) {
209 | this.screen[y][x] = color + Plot.ChartHorizontal[state];
210 | } else {
211 | this.screen[lastY][x] = color + Plot.ChartHorizontal[state];
212 | this.screen[y][x] = color + Plot.ChartVertical[state];
213 | }
214 | }
215 |
216 | if (y !== lastY) {
217 | this._fillVertical(color, x, Math.min(y, lastY) + 1, Math.max(y, lastY) - 1);
218 | }
219 |
220 | lastY = y;
221 | lastState = state;
222 | }
223 | }
224 |
225 | const titleLabel = new Label(
226 | this.title, this.width, this.height, this.horizontalBoundary, this.titlePosition, this.titleSpacing
227 | );
228 | titleLabel.foregroundColor = this.titleForeground;
229 | titleLabel.backgroundColor = this.titleBackground;
230 | titleLabel.draw(this.screen, xOffset, 0);
231 | }
232 |
233 | public paint(): string {
234 | this.redraw();
235 |
236 | return this.screen.map(row => row.join("")).join("\n") + Color.reset;
237 | }
238 |
239 | private _drawAxis(yOffset: number, axisValues: number[]) {
240 | const size = axisValues.length;
241 | const labelPadding = Math.max(
242 | Math.abs(axisValues[0]).toFixed(this.axisLabelsFraction).length,
243 | Math.abs(axisValues[size - 1]).toFixed(this.axisLabelsFraction).length) + 1;
244 |
245 | for (let i = 0; i < this.height; i++) {
246 | const index = this.height - 1 - i;
247 | this.screen[index][labelPadding + 1] = Color.default + Plot.AxisSymbol;
248 |
249 | const labelIndex = i - yOffset;
250 | if (labelIndex >= 0 && labelIndex < size) {
251 | const axisValue = axisValues[labelIndex];
252 | const label = Utils.toFixed(axisValue, this.axisLabelsFraction).padStart(labelPadding, " ");
253 |
254 | for (let j = 0; j < label.length; j++) {
255 | this.screen[index][j] = Color.default + label[j];
256 | }
257 | }
258 | }
259 |
260 | return labelPadding;
261 | }
262 |
263 | private _clear() {
264 | for (let i = 0; i < this.height; i++) {
265 | this.screen[i].fill(Plot.SpaceSymbol);
266 | }
267 | }
268 |
269 | private _handleOverflow(data: number[], overflow: PlotSeriesOverflow, maxLength: number) {
270 | if (data.length <= maxLength) return data;
271 |
272 | switch (overflow) {
273 | case PlotSeriesOverflow.linearScale:
274 | return Utils.shrinkData(data, maxLength, Utils.linearDistribution, this.aggregationFn);
275 |
276 | case PlotSeriesOverflow.logScale:
277 | return Utils.shrinkData(data, maxLength, this._invertedLogDistribution.bind(this, data), this.aggregationFn);
278 |
279 | case PlotSeriesOverflow.clamp:
280 | return Utils.shrinkData(data, maxLength, this._skipDistribution.bind(this), this.aggregationFn);
281 |
282 | default:
283 | throw new Error(`Unsupported overflow function: ${overflow}`);
284 | }
285 | }
286 |
287 | private _skipDistribution(_: number, max: number, count: number): Iterable {
288 | return Utils.linearDistribution(max - count + 1, max, count);
289 | }
290 |
291 | private* _invertedLogDistribution(data: number[], min: number, max: number, count: number): Iterable {
292 | const overflowCount = data.length - count;
293 | const ratio = Math.min(1, overflowCount / 50);
294 | yield* Utils.invertedLogDistribution(min, max, count, ratio);
295 | }
296 |
297 | private _fillVertical(color: Color, x: number, fromY: number, toY: number) {
298 | for (let i = fromY; i <= toY; i++) {
299 | this.screen[i][x] = color + Plot.ChartVertical[0];
300 | }
301 | }
302 | }
--------------------------------------------------------------------------------
/src/utils.ts:
--------------------------------------------------------------------------------
1 | export type DistributionFn = (min: number, max: number, count: number) => Iterable
2 |
3 | export type AggregationFn = (data: number[], from: number, to: number) => number;
4 |
5 | export function toFixed(value: number, maxFraction = 2) {
6 | let label = value.toFixed(maxFraction)
7 | const pointIndex = label.indexOf(".")
8 | let trimIndex = label.length;
9 | for (; trimIndex > pointIndex; trimIndex--) {
10 | if (label[trimIndex - 1] !== '0') break;
11 | }
12 |
13 | if (trimIndex > 0 && label[trimIndex - 1] === ".") {
14 | trimIndex--;
15 | }
16 |
17 | return label.slice(0, trimIndex);
18 | }
19 |
20 | export function minMax(values: number[]): [number, number] {
21 | let max = Number.NEGATIVE_INFINITY;
22 | let min = Number.POSITIVE_INFINITY;
23 |
24 | for (const value of values) {
25 | if (Number.isNaN(value)) continue;
26 |
27 | min = Math.min(min, value);
28 | max = Math.max(max, value);
29 | }
30 |
31 | return [min, max];
32 | }
33 |
34 | export function minMax2d(values: number[][]): [number, number] {
35 | let max = Number.NEGATIVE_INFINITY;
36 | let min = Number.POSITIVE_INFINITY;
37 |
38 | for (const row of values) {
39 | const [localMin, localMax] = minMax(row);
40 | if (!Number.isFinite(localMin)) continue;
41 |
42 | min = Math.min(min, localMin);
43 | max = Math.max(max, localMax);
44 | }
45 |
46 | if (Number.isFinite(min)) {
47 | return [min, max];
48 | }
49 |
50 | return [0, 0];
51 | }
52 |
53 | export function* linearDistribution(min: number, max: number, count: number): Iterable {
54 | if (count < 2) throw new Error("Count should be greater or equals 2");
55 | if (min > max) [min, max] = [max, min];
56 |
57 | const step = (max - min) / (count - 1);
58 | for (let i = 0; i < count; i++) {
59 | yield min + i * step;
60 | }
61 | }
62 |
63 | export function* logDistribution(min: number, max: number, count: number, ratio: number = 1): Iterable {
64 | if (count < 2) throw new Error("Count should be greater or equals 2");
65 | if (min > max) [min, max] = [max, min];
66 |
67 | let offset = 0;
68 | if (min < 1) {
69 | offset = Math.abs(min) + 1;
70 | min += offset;
71 | max += offset;
72 | }
73 |
74 | ratio = Math.max(0, Math.min(1, ratio));
75 | for (let i = 0; i < count; i++) {
76 | // Linear distribution value between 0 and 1
77 | const linearValue = i / (count - 1);
78 |
79 | // Logarithmic distribution value between 0 and 1
80 | // Special case is i=0, since 10^0 = 1, and so we get 0.1 and thus skip `min` border
81 | const logarithmicValue = i > 0 ? Math.pow(10, linearValue) / 10 : 0;
82 |
83 | // Applying ratio to interpolate between linear and logarithmic distributions
84 | const interpolatedValue = (1 - ratio) * linearValue + ratio * logarithmicValue;
85 |
86 | // Scaling the interpolated value to the desired range
87 | const scaledValue = min + interpolatedValue * (max - min);
88 |
89 | yield scaledValue - offset;
90 | }
91 | }
92 |
93 | export function* invertedLogDistribution(min: number, max: number, count: number, ratio: number = 1): Iterable {
94 | const values = Array.from(logDistribution(min, max, count, ratio)).reverse();
95 |
96 | let prev = values[0];
97 | let last = min;
98 | for (const value of values) {
99 | const delta = (prev - value);
100 | yield last + delta;
101 |
102 | prev = value;
103 | last += delta;
104 | }
105 | }
106 |
107 | export function aggregateAverage(data: number[], from: number, to: number): number {
108 | if (from >= to) return data[to];
109 |
110 | const length = to - from + 1;
111 | let value = 0;
112 | for (let i = from; i <= to; i++) {
113 | value += data[i] / length;
114 | }
115 |
116 | return value;
117 | }
118 |
119 | export function aggregateMax(data: number[], from: number, to: number): number {
120 | if (from >= to) return data[to];
121 |
122 | let value = data[from];
123 | for (let i = from; i <= to; i++) {
124 | value = Math.max(value, data[i]);
125 | }
126 |
127 | return value;
128 | }
129 |
130 | export function aggregateMin(data: number[], from: number, to: number): number {
131 | if (from >= to) return data[to];
132 |
133 | let value = data[from];
134 | for (let i = from; i <= to; i++) {
135 | value = Math.min(value, data[i]);
136 | }
137 |
138 | return value;
139 | }
140 |
141 | export function aggregateSkip(data: number[], from: number, to: number) {
142 | return data[to];
143 | }
144 |
145 | export function shrinkData(data: number[], maxLength: number, distributionFn: DistributionFn, aggregationFn: AggregationFn) {
146 | if (data.length <= maxLength) return data;
147 | const shrunk = new Array(maxLength);
148 |
149 | let i = 0;
150 | let prevIndex;
151 | for (let index of distributionFn(0, data.length - 1, maxLength)) {
152 | index = Math.round(index);
153 | if (prevIndex === undefined) prevIndex = index;
154 |
155 | shrunk[i++] = aggregationFn(data, prevIndex, index);
156 | prevIndex = index + 1;
157 | }
158 |
159 | return shrunk;
160 | }
161 |
162 | export function findClosestIndexSorted(data: number[], value: number): number {
163 | let index = 0;
164 | let left = 0;
165 | let right = data.length - 1;
166 |
167 | while (left <= right) {
168 | index = left + Math.floor((right - left) / 2);
169 | const current = data[index];
170 |
171 | if (value < current) {
172 | right = index - 1;
173 | } else if (value > current) {
174 | left = index + 1;
175 | } else {
176 | return index;
177 | }
178 | }
179 |
180 | //value is outside [min; max] range
181 | if (left === 0 || left >= data.length) {
182 | return index;
183 | }
184 |
185 | const lowerDiff = Math.abs(data[left - 1] - value);
186 | const upperDiff = Math.abs(data[left] - value);
187 | return lowerDiff < upperDiff ? left - 1 : left;
188 | }
189 |
190 | export function zoomData(data: number[], maxLength: number): number[] {
191 | if (data.length === 0 && data.length >= maxLength) return data;
192 |
193 | const zoomed = new Array(maxLength);
194 | let outIndex = 0;
195 | for (const zoomedIndex of linearDistribution(0, data.length - 1, maxLength)) {
196 | zoomed[outIndex++] = data[Math.round(zoomedIndex)];
197 | }
198 |
199 | return zoomed;
200 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2020",
4 | "module": "es2020",
5 | "lib": [
6 | "es2020",
7 | "dom"
8 | ],
9 | "moduleResolution": "node",
10 | "rootDir": "src",
11 | "outDir": "lib",
12 | "esModuleInterop": true,
13 | "strict": true,
14 | "noImplicitAny": true,
15 | "skipLibCheck": true,
16 | "forceConsistentCasingInFileNames": true,
17 | "noImplicitReturns": true,
18 | "noFallthroughCasesInSwitch": true,
19 | "declaration": true,
20 | "downlevelIteration": true,
21 | "importHelpers": true,
22 | },
23 | "include": [
24 | "./src/**/*.ts",
25 | "./examples/**/*.ts"
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2020",
4 | "module": "es2020",
5 | "lib": [
6 | "es2020"
7 | ],
8 | "allowJs": true,
9 | "moduleResolution": "node",
10 | "rootDir": "src",
11 | "outDir": "lib",
12 | "esModuleInterop": true,
13 | "strict": true,
14 | "noImplicitAny": true,
15 | "skipLibCheck": true,
16 | "forceConsistentCasingInFileNames": true,
17 | "noImplicitReturns": true,
18 | "noFallthroughCasesInSwitch": true,
19 | "downlevelIteration": true,
20 | "importHelpers": true,
21 | "allowSyntheticDefaultImports": true,
22 | "sourceMap": false,
23 | "declaration": true,
24 | "emitDeclarationOnly": true
25 | },
26 | "include": [
27 | "./src/**/*.ts",
28 | ]
29 | }
--------------------------------------------------------------------------------