This commit is contained in:
2025-09-08 20:55:29 -06:00
commit 3451149691
12 changed files with 2419 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
.vscode
node_modules
dist

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Petr Vavrin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

69
README.md Normal file
View File

@@ -0,0 +1,69 @@
## WebSerial TERMINAL
is a terminal emulator that allows you to connect to a serial device from your web browser.
Based on the WebSerial API and xterm.js.
### Online version
[terminal.vavrin.eu](https://terminal.vavrin.eu/)
### Features
- Connect to a serial device from your web browser
- Predefined baud rates - 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
- Default baud rate is 115200
- The last used baud rate is saved in the local storage
- Adjustable font size
- From 10 to 40
- Default is 15
- The last used font size is saved in the local storage
- Font size can be changed using these methods:
- `Ctrl + Mouse Wheel` inside terminal to decrease or increase font size
- `Mouse Wheen` inside font size input to decrease or increase font size
- Clicking on minus or plus button to decrease or increase font size
- Send keystrokes to the connected device and receive responses
- Button `Ctrl+C` to send the break signal
- Button `Ctrl+D` to send the end of transmission signal
- Button `Scroll to bottom` to scroll to the bottom of the terminal
- Button `Show Buffer` to show the buffer of the terminal
- The buffer is limited to 512 bytes
- The buffer is circular and the oldest data is overwritten by the newest data
- The buffer shows hexadecimal and ASCII representation of the data
- Values with yellow text color or background are the control characters
- Values with black background are read bytes
- Values with colored background and black text are written bytes
- When mouse hovers over the buffer cell, the hexadecimal and ASCII representation is highlighted and value is shown in the top bar
- When mouse double clicks on the buffer cell, then value is freezed
- When mouse clicks on the buffer cell, then value is unfreezed
- Button `Reset stats` to reset the statistics about read and written bytes
### Build
- Clone the repository
- Run `yarn install` or `npm install`
- Run `yarn build` or `npm run build`
- In `dist` folder, you can find these folders:
- `default` - separated local and remote assets
- `single-file` - contains all local and remote assets in one file
- `single-file-with-remote-assets` - contains all local in one file, remote assets are loaded from the web
### Run
- You can run the terminal by opening the `index.html` file in your browser from the `dist` folders.
- Or you can run it from a HTTPS server/webhosting.
- You can copy `index.html` from `dist/single-file` folder to your microcontroller and run the terminal from there even without internet connection.
### Resources
- [WebSerial API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API)
- [xterm.js](https://xtermjs.org/)

152
build.js Normal file
View File

@@ -0,0 +1,152 @@
const fs = require('fs');
const path = require('path');
const axios = require('axios');
const { minify } = require('html-minifier-terser');
async function inlineAsset(html, params) {
let asset;
const filePath = params.path.startsWith('http') ? params.path : path.join(params.sourceFolder, params.path);
if (fs.existsSync(filePath)) {
if (!params.inlineLocalAssets) {
if (filePath.includes('assets')) {
const assetPath = path.join(filePath.split('assets')[1]);
const targetPath = path.join(params.targetFolder, assetPath);
const targetFolder = path.dirname(targetPath);
const htmlAssetPath = `.${assetPath.replace(/\\/g, '/')}`;
if (!fs.existsSync(targetFolder)) {
fs.mkdirSync(targetFolder, { recursive: true });
}
fs.copyFileSync(filePath, targetPath);
if (params.originalTag.toLowerCase() === 'link') {
html = html.replace(params.regex, `<link rel="stylesheet" href="${htmlAssetPath}" />`);
} else if (params.originalTag.toLowerCase() === 'script') {
html = html.replace(params.regex, `<script src="${htmlAssetPath}"></script>`);
}
}
return html;
}
asset = fs.readFileSync(filePath, 'utf8');
} else {
if (!params.inlineRemoteAssets) {
return html;
}
asset = (await axios.get(filePath)).data;
}
return html.replace(params.regex, `<${params.tag}>\n${asset}\n</${params.tag}>`);
}
function cleanTargetPath(targetDir) {
if (!fs.existsSync(targetDir)) {
return;
}
fs.readdirSync(targetDir).forEach((file) => {
const entryPath = path.join(targetDir, file);
const stat = fs.lstatSync(entryPath);
if (stat.isFile()) {
fs.unlinkSync(entryPath);
} else if (stat.isDirectory()) {
cleanTargetPath(entryPath);
}
});
fs.rmdirSync(targetDir);
}
async function inlineAssets(params) {
const sourceFolder = params.sourceFolder;
const targetFolder = params.targetFolder;
console.log(`Inlining assets from ${sourceFolder} to ${targetFolder}`);
const inputFile = path.join(sourceFolder, params.inputFile);
const outputFile = path.join(targetFolder, 'index.html');
let html = fs.readFileSync(inputFile, 'utf8');
const inlineLocalAssets = params.inlineLocalAssets || false;
const inlineRemoteAssets = params.inlineRemoteAssets || false;
cleanTargetPath(targetFolder);
if (!fs.existsSync(targetFolder)) {
fs.mkdirSync(targetFolder, { recursive: true });
}
// Match and inline CSS links
const cssLinks = [...html.matchAll(/<link[^>]*?\s+href=["'](.*?)["'][^>]*?>/gs)];
for (const match of cssLinks) {
html = await inlineAsset(html, {
path: match[1],
regex: match[0],
originalTag: 'link',
tag: 'style',
sourceFolder,
targetFolder,
inlineLocalAssets,
inlineRemoteAssets,
});
}
// Match and inline JavaScript src
const scriptLinks = [...html.matchAll(/<script[^>]*?\s+src=["'](.*?)["'][^>]*?>\s*<\/script>/gs)];
for (const match of scriptLinks) {
html = await inlineAsset(html, {
path: match[1],
regex: match[0],
originalTag: 'script',
tag: 'script',
sourceFolder,
targetFolder,
inlineLocalAssets,
inlineRemoteAssets,
});
}
// Minify the HTML
const minifiedHtml = await minify(html, {
collapseWhitespace: true,
removeComments: true,
removeRedundantAttributes: true,
removeEmptyAttributes: true,
minifyCSS: true,
minifyJS: true,
});
// Save the minified HTML file
fs.writeFileSync(outputFile, minifiedHtml, 'utf8');
console.log(`Saved minified HTML to ${outputFile}`);
}
const defaultBuild = {
sourceFolder: './src',
inputFile: './index.html',
targetFolder: './dist/default',
inlineLocalAssets: false,
inlineRemoteAssets: false,
};
const singleFileWithRemoteAssets = {
sourceFolder: './src',
inputFile: './index.html',
targetFolder: './dist/single-file-with-remote-assets',
inlineLocalAssets: true,
inlineRemoteAssets: false,
};
const singleFile = {
sourceFolder: './src',
inputFile: './index.html',
targetFolder: './dist/single-file',
inlineLocalAssets: true,
inlineRemoteAssets: true,
};
inlineAssets(defaultBuild);
inlineAssets(singleFileWithRemoteAssets);
inlineAssets(singleFile);

1
eslint.config.js Normal file
View File

@@ -0,0 +1 @@
module.exports = [{}];

14
package.json Normal file
View File

@@ -0,0 +1,14 @@
{
"name": "webserial_term",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"axios": "^1.11.0",
"eslint": "^9.24.0",
"html-minifier-terser": "^7.2.0"
},
"scripts": {
"build": "node build.js"
}
}

316
src/assets/css/styles.css Normal file
View File

@@ -0,0 +1,316 @@
html {
overflow: hidden;
}
* {
font-family: 'Ubuntu Mono', Menlo, Consolas, 'DejaVu Sans Mono', 'Courier New', Courier, monospace;
outline: none;
}
body {
background-color: #000000;
color: #ffffff;
margin: 0;
padding: 0;
}
#app {
visibility: hidden;
display: flex;
flex-direction: column;
height: 100vh;
margin: 0;
overflow: hidden;
}
a {
color: #d9cb0a;
text-decoration: none;
}
#top-bar,
#bottom-bar {
display: flex;
justify-content: flex-start;
align-items: center;
flex-direction: row;
padding: 5px 10px;
background-color: #272727;
height: 25px !important;
white-space: nowrap;
color: #aaaaaa;
}
#top-bar {
user-select: none;
border-bottom: 1px solid #1a1a1a;
}
#bottom-bar {
border-top: 1px solid #1a1a1a;
}
.corner::before {
content: '';
position: absolute;
top: 0;
left: 0;
border-bottom: 7px solid transparent;
border-left: 7px solid #272727;
width: 0;
}
.toolbar-button,
.toolbar-input,
.toolbar-select {
align-items: center;
background-color: #181818;
border-bottom: 1px solid #353535;
border-right: 1px solid #353535;
border: 0px solid #333333;
color: #aaaaaa;
display: flex;
height: 100%;
justify-content: center;
line-height: 100%;
padding: 0 10px;
position: relative;
text-align: center;
}
.toolbar-button {
font-size: 14px;
cursor: pointer;
user-select: none;
}
.toolbar-button:hover,
.toolbar-button.active {
color: #000000;
background-color: #d9cb0a;
}
.toolbar-space {
margin-right: 15px;
}
.toolbar-spacer {
flex-grow: 1;
}
.toolbar-input-label {
font-size: 14px;
color: #aaaaaa;
margin-right: 10px;
}
.toolbar-input {
width: 25px !important;
font-size: 15px;
}
.toolbar-input::-webkit-outer-spin-button,
.toolbar-input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.toolbar-select {
font-size: 15px;
}
.toolbar-icons {
width: 60px;
}
.toolbar-svg-icon {
width: 30px !important;
height: 30px !important;
margin-top: 2px;
}
#main {
flex-grow: 1;
margin: 10px;
display: flex;
flex-direction: column;
height: 100vh;
margin: 0;
overflow: hidden;
}
#terminal-container {
flex-grow: 1;
margin: 10px;
overflow: hidden;
}
.terminal-background {
position: absolute;
width: 100%;
height: calc(100% - 100px);
pointer-events: none;
font-family: 'Ubuntu Mono', Menlo, Consolas, 'DejaVu Sans Mono', 'Courier New', Courier, monospace;
}
.xterm .xterm-viewport {
overflow-y: scroll;
cursor: default;
position: absolute;
right: 0;
left: 0;
top: 0;
bottom: 0;
scrollbar-color: #333333 #111111;
scrollbar-width: thin;
background-color: transparent !important;
}
.xterm-viewport::-webkit-scrollbar {
background-color: #333;
width: 8px;
}
.xterm-viewport::-webkit-scrollbar-thumb {
background: #00ccff;
}
#button-connect {
width: 150px;
}
#transfer-stats {
overflow: hidden;
margin-left: 10px;
white-space: nowrap;
text-overflow: ellipsis;
}
#data-table-info {
display: none;
position: absolute;
top: 45px;
right: 30px;
height: 40px;
flex-direction: row;
justify-content: start;
overflow: hidden;
display: inline-block;
border: 1px solid #202020;
background-color: #0a0a0a;
}
.data-table-info-title {
font-size: 14px;
color: #aaaaaa;
margin-right: 10px;
}
.data-table-info-cell {
margin-left: 20px;
}
.data-table-info-label {
height: 14px;
font-size: 10px;
text-align: center;
opacity: 0.5;
}
.data-table-info-value {
text-align: center;
font-size: 20px;
}
.data-table-info-value svg {
display: block;
margin: auto;
}
#data-table-info-dec,
#data-table-info-hex,
#data-table-info-ascii {
width: 45px;
}
#data-table-info-detail {
width: 285px;
}
#data-table-info-bin {
width: 80px;
}
#data-tables {
position: absolute;
display: none;
top: 90px;
right: 30px;
flex-direction: row;
justify-content: start;
overflow-y: auto;
overflow-x: hidden;
scrollbar-color: #333333 #111111;
scrollbar-width: thin;
pointer-events: none;
}
#data-table-hex,
#data-table-ascii {
display: grid;
grid-template-columns: repeat(16, 1fr);
font-size: 14px;
border-collapse: collapse;
border: 1px solid #202020;
gap: 0;
box-sizing: border-box;
height: max-content;
pointer-events: auto;
}
#data-table-ascii {
margin-left: 10px;
}
#data-table-hex div,
#data-table-ascii div {
display: table-cell;
white-space: pre;
overflow: hidden;
text-align: center;
cursor: default;
height: 18px !important;
line-height: 18px !important;
background-color: #0a0a0a;
}
#data-table-hex div {
width: 22px !important;
border: 1px solid #000000;
}
#data-table-ascii div {
width: 18px !important;
border: 1px solid #000000;
}
.cell,
.cell-in {
font-weight: 400;
background-color: #0a0a0a;
}
.cell {
color: #313131;
}
.cell-in {
color: #ababab;
}
.cell-in-escape {
color: #d9cb0a;
}
#data-table-ascii .cell-in-escape,
#data-table-ascii .cell-out-escape,
#data-table-ascii .cell-highlight-escape {
font-size: 10px;
}
.cell-out,
.cell-out-escape {
font-weight: 700;
color: #0a0a0a;
}
.cell-out {
background-color: #898989 !important;
}
.cell-out-escape {
background-color: #b7ab00 !important;
}
.cell-highlight,
.cell-highlight-escape {
font-weight: 700;
color: #c8c8c8;
background-color: #05198b !important;
}
#about {
display: none;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 460px;
padding: 20px;
background-color: #0a0a0a;
border: 1px solid #202020;
box-shadow: 0 0 10px #000000;
z-index: 100;
}
#about pre {
position: relative;
text-align: left;
display: inline-block;
white-space: pre-wrap;
word-wrap: break-word;
padding: 0px;
margin: 0px;
}
@media (max-width: 880px) {
.toolbar-input-label {
display: none;
}
}

53
src/assets/js/config.js Normal file
View File

@@ -0,0 +1,53 @@
class Config {
constructor(defaults) {
this.config = {};
this.defaults = defaults;
this.init();
}
init() {
if (window.localStorage) {
const storedConfig = localStorage.getItem('config');
if (storedConfig) {
try {
const storedConfigJSON = JSON.parse(storedConfig);
for (let key of Object.keys(storedConfigJSON)) {
if (storedConfigJSON[key] === null) {
continue;
}
this.config[key] = storedConfigJSON[key];
}
} catch (error) {
console.error('Error parsing stored config');
}
}
}
for (const key in this.defaults) {
if (!(key in this.config)) {
this.config[key] = this.defaults[key];
}
}
}
saveConfig() {
if (window.localStorage) {
localStorage.setItem('config', JSON.stringify(this.config));
}
}
get(key) {
if (key in this.config) {
return this.config[key];
}
if (key in this.defaults) {
return this.defaults[key];
}
return null;
}
set(key, value) {
this.config[key] = value;
this.saveConfig();
}
}

228
src/assets/js/io-buffer.js Normal file
View File

@@ -0,0 +1,228 @@
class IOBuffer {
constructor(options) {
this.dataTables = options.dataTables;
this.dataTableHex = options.dataTableHex;
this.dataTableInfoLock = options.dataTableInfoLock;
this.dataTableInfoDirection = options.dataTableInfoDirection;
this.dataTableAscii = options.dataTableAscii;
this.dataTableInfoHex = options.dataTableInfoHex;
this.dataTableInfoDec = options.dataTableInfoDec;
this.dataTableInfoBin = options.dataTableInfoBin;
this.dataTableInfoAscii = options.dataTableInfoAscii;
this.dataTableInfoDetail = options.dataTableInfoDetail;
this.freezedCellInfo = false;
this.size = options.bufferSize;
this.rowLength = options.rowLength;
this.cellsSize = this.size + this.rowLength;
this.buffer = new Array(this.size);
this.cells = new Array(this.cellsSize);
this.head = 0;
this.tail = 0;
this.rowOffset = 0;
this.releaseNodes = [];
this.classes = {
in: 'cell-in',
out: 'cell-out',
init: 'cell',
};
this.escapeChars = [
{ value: 'NUL', label: 'NULL character' },
{ value: 'SOH', label: 'Start of Heading' },
{ value: 'STX', label: 'Start of Text' },
{ value: 'ETX', label: 'End of Text' },
{ value: 'EOT', label: 'End of Transmission' },
{ value: 'ENQ', label: 'Enquiry' },
{ value: 'ACK', label: 'Acknowledge' },
{ value: 'BEL', label: 'Bell' },
{ value: 'BS', label: 'Backspace' },
{ value: 'HT', label: 'Horizontal Tab' },
{ value: 'LF', label: 'Line feed' },
{ value: 'VT', label: 'Vertical Tab' },
{ value: 'FF', label: 'Form Feed' },
{ value: 'CR', label: 'Carriage return' },
{ value: 'SO', label: 'Shift Out' },
{ value: 'SI', label: 'Shift In' },
{ value: 'DLE', label: 'Data Link Escape' },
{ value: 'DC1', label: 'Device Control (XOn)' },
{ value: 'DC2', label: 'Device Control' },
{ value: 'DC3', label: 'Device Control (XOff)' },
{ value: 'DC4', label: 'Device Control' },
{ value: 'NAK', label: 'Negative Acknowledge' },
{ value: 'SYN', label: 'Synchronous Idle' },
{ value: 'ETB', label: 'End of Transmission Block' },
{ value: 'CAN', label: 'Cancel' },
{ value: 'EM', label: 'End of Medium' },
{ value: 'SUB', label: 'Substitute' },
{ value: 'ESC', label: 'Escape' },
{ value: 'FS', label: 'File Separator' },
{ value: 'GS', label: 'Group Separator' },
{ value: 'RS', label: 'Record Separator' },
{ value: 'US', label: 'Unit Separator' },
];
this.prepareTableCells();
}
prepareTableCells() {
for (let index = 0; index < this.cellsSize; index++) {
const hexCell = document.createElement('div');
const asciiCell = document.createElement('div');
this.dataTableHex.appendChild(hexCell);
this.dataTableAscii.appendChild(asciiCell);
this.cells[index] = {
nodeHex: hexCell,
nodeAscii: asciiCell,
};
}
this.reset();
}
reset() {
this.head = 0;
this.tail = 0;
this.rowOffset = 0;
this.cells.forEach((cell, index) => {
cell.dir = 'init';
cell.nodeHex.dataset.index = index;
cell.nodeHex.className = 'cell';
cell.nodeHex.textContent = '  ';
cell.nodeAscii.dataset.index = index;
cell.nodeAscii.className = 'cell';
cell.nodeAscii.textContent = ' ';
cell.value = null;
});
}
push(data, dir) {
const now = Date.now();
for (let i = 0; i < data.length; i++) {
this.buffer[this.tail] = {
data: data[i],
ts: now,
dir,
};
this.tail = (this.tail + 1) % this.size;
if (this.tail === this.head) {
this.head = (this.head + 1) % this.size;
}
}
this.rowOffset = (this.rowOffset + data.length) % this.rowLength;
}
getCellClassName(cell) {
let className = cell.highlight ? 'cell-highlight' : this.classes[cell.dir];
if (cell.value !== null && cell.value < 32) {
className = `${className}-escape`;
}
return className;
}
updateCell(index, dir, value) {
const cell = this.cells[index];
if (cell.value !== value) {
cell.nodeHex.textContent = value === null ? '  ' : value.toString(16).toUpperCase().padStart(2, '0');
if (value === null) {
cell.nodeAscii.textContent = ' ';
} else if (value < 32) {
cell.nodeAscii.innerHTML = this.escapeChars[value].value;
} else {
cell.nodeAscii.textContent = String.fromCharCode(value);
}
cell.value = value;
}
if (cell.dir !== dir) {
cell.dir = dir;
}
const className = this.getCellClassName(cell);
if (cell.nodeHex.className !== className) {
cell.nodeHex.className = className;
cell.nodeAscii.className = className;
}
}
showInfo(value, dir) {
this.dataTableInfoDirection.textContent = dir === 'init' ? '' : dir.toUpperCase();
this.dataTableInfoHex.textContent = value.toString(16).toUpperCase().padStart(2, '0');
this.dataTableInfoDec.textContent = value.toString(10);
this.dataTableInfoBin.textContent = value.toString(2).padStart(8, '0');
this.dataTableInfoAscii.textContent = value < 32 ? this.escapeChars[value].value : String.fromCharCode(value);
this.dataTableInfoDetail.textContent = value < 32 ? this.escapeChars[value].label : '';
this.dataTableInfoLock.style.display = this.freezedCellInfo ? 'block' : 'none';
}
cleanInfo() {
this.dataTableInfoDirection.textContent = '';
this.dataTableInfoHex.textContent = '';
this.dataTableInfoDec.textContent = '';
this.dataTableInfoBin.textContent = '';
this.dataTableInfoAscii.textContent = '';
this.dataTableInfoDetail.textContent = '';
this.dataTableInfoLock.style.display = 'none';
}
highlightCell(index, state) {
const cell = this.cells[index];
cell.highlight = state;
const className = this.getCellClassName(cell);
cell.nodeHex.className = className;
cell.nodeAscii.className = className;
if (this.freezedCellInfo) {
return;
}
if (state && cell.value !== null) {
this.showInfo(cell.value, cell.dir);
} else {
this.cleanInfo();
}
}
freezeCellInfo(index) {
const cell = this.cells[index];
this.freezedCellInfo = true;
this.showInfo(cell.value, cell.dir);
this.dataTableInfoLock.style.display = 'block';
}
unfreezeCellInfo() {
this.freezedCellInfo = false;
this.cleanInfo();
this.dataTableInfoLock.style.display = 'none';
}
redraw() {
let index = this.head;
let cellIndex = 0;
if (this.head !== 0) {
for (let i = 0; i < this.rowOffset; i++) {
this.updateCell(cellIndex, 'init', null);
cellIndex++;
}
}
while (index !== this.tail) {
const item = this.buffer[index];
this.updateCell(cellIndex, item.dir, item.data);
index = (index + 1) % this.size;
cellIndex++;
}
const cellsLeft = this.rowLength - (cellIndex % this.rowLength);
for (let i = 0; i < cellsLeft; i++) {
this.updateCell(cellIndex, 'init', null);
cellIndex++;
}
}
resize(newHeight) {
this.dataTables.style.height = `${newHeight - 60}px`;
this.dataTables.scrollTop = this.dataTables.scrollHeight;
}
}

453
src/assets/js/main.js Normal file
View File

@@ -0,0 +1,453 @@
document.addEventListener('DOMContentLoaded', () => {
const [
app,
terminalContainer,
connectButton,
selectSerialPortBaudrate,
buttonCtrlC,
buttonCtrlD,
buttonScrollToBottom,
buttonShowAbout,
buttonShowBuffer,
buttonResetStats,
inputFontSize,
buttonFontSizeMinus,
buttonFontSizePlus,
svgDevice,
svgToDevice,
svgFromDevice,
transferStats,
dataTableInfo,
dataTables,
dataTableHex,
dataTableAscii,
dataTableInfoLock,
dataTableInfoDirection,
dataTableInfoHex,
dataTableInfoDec,
dataTableInfoBin,
dataTableInfoAscii,
dataTableInfoDetail,
terminalBackgroundText,
] = [
'app',
'terminal-container',
'button-connect',
'select-serial-port-baudrate',
'button-ctrl-c',
'button-ctrl-d',
'button-scroll-to-bottom',
'button-show-about',
'button-show-buffer',
'button-reset-stats',
'input-font-size',
'button-font-size-minus',
'button-font-size-plus',
'svg-device',
'svg-to-device',
'svg-from-device',
'transfer-stats',
'data-table-info',
'data-tables',
'data-table-hex',
'data-table-ascii',
'data-table-info-lock',
'data-table-info-direction',
'data-table-info-hex',
'data-table-info-dec',
'data-table-info-bin',
'data-table-info-ascii',
'data-table-info-detail',
'terminal-background-text',
].map((id) => document.getElementById(id));
// small animation on terminal background just for fun
const backgroundDot = ['•', '•', '•'];
const backgroundText = ['T', 'E', 'R', 'M', 'I', 'N', 'A', 'L'];
function animationPhase(text, stepDelay, endDelay, callback) {
terminalBackgroundText.textContent = '';
const interval = setInterval(() => {
terminalBackgroundText.textContent = terminalBackgroundText.textContent + text.shift();
if (text.length) return;
clearInterval(interval);
if (endDelay && callback) {
setTimeout(callback, endDelay);
}
}, stepDelay);
}
animationPhase(backgroundDot, 200, 400, () => {
animationPhase(backgroundText, 70);
});
let port;
let reader;
let portReadedChars = 0;
let portWritedChars = 0;
let portLastReadedChars = 0;
let portLastWritedChars = 0;
let showAbout = false;
let showDataBuffer = false;
let lastHighlightIndex = null;
const ioBufferOptions = {
dataTables,
dataTableHex,
dataTableAscii,
dataTableInfoLock,
dataTableInfoDirection,
dataTableInfoHex,
dataTableInfoDec,
dataTableInfoBin,
dataTableInfoAscii,
dataTableInfoDetail,
bufferSize: 512,
rowLength: 16,
};
const defaultConfig = {
fontSize: 12,
baudRate: 115200,
};
const ioBuffer = new IOBuffer(ioBufferOptions);
const config = new Config(defaultConfig);
inputFontSize.value = parseInt(config.get('fontSize'));
selectSerialPortBaudrate.value = parseInt(config.get('baudRate'));
const { Terminal } = window;
const { FitAddon } = window.FitAddon;
const terminal = new Terminal({
scrollback: 1000,
cursorBlink: true,
fontFamily: '"Ubuntu Mono", Menlo, Consolas, "DejaVu Sans Mono", "Courier New", Courier, monospace',
theme: {
background: 'transparent',
allowTransparency: true,
// selectionBackground: '#bbbbbb',
// selectionForeground: '#000000',
},
});
const fitAddon = new FitAddon();
terminal.loadAddon(fitAddon);
terminal.onTitleChange((title) => {
document.title = title;
});
terminal.attachCustomKeyEventHandler((event) => {
if (event.ctrlKey && (event.type === 'keydown' || event.type === 'keyup')) {
let button = null;
if (event.code === 'KeyC') {
button = buttonCtrlC;
} else if (event.code === 'KeyD') {
button = buttonCtrlD;
} else {
return;
}
if (event.type === 'keydown') {
button.classList.add('active');
} else if (event.type === 'keyup') {
button.classList.remove('active');
}
}
});
terminal.open(terminalContainer);
fitAddon.fit();
terminal.onResize(function () {
ioBuffer.resize(terminalContainer.clientHeight);
});
terminal.onData(async (data) => {
if (port && port.writable) {
const writer = port.writable.getWriter();
const chars = new TextEncoder().encode(data);
portWritedChars += chars.length;
ioBuffer.push(chars, 'out');
await writer.write(chars);
writer.releaseLock();
}
});
if (navigator && 'serial' in navigator) {
terminal.writeln('WebSerial Terminal - Click on "Connect to Serial" to start.');
} else {
terminal.writeln('Terminal error: WebSerial not supported');
terminal.writeln('Please use a browser that supports it.');
terminal.writeln(
'Supported browsers: Chrome 89+, Edge 89+, Opera 75+ and other browsers based on Chromium 89+.'
);
}
function updateToolbar() {
if (!navigator || !('serial' in navigator)) {
connectButton.setAttribute('disabled', 'disabled');
}
const connected = !!port;
connectButton.textContent = connected ? 'Disconnect' : 'Connect to Serial';
buttonCtrlC.style.display = connected ? 'flex' : 'none';
buttonCtrlD.style.display = connected ? 'flex' : 'none';
buttonScrollToBottom.style.display = connected ? 'flex' : 'none';
buttonShowBuffer.textContent = showDataBuffer ? 'Hide Buffer' : 'Show Buffer';
if (connected) {
selectSerialPortBaudrate.setAttribute('disabled', 'disabled');
} else {
selectSerialPortBaudrate.removeAttribute('disabled');
}
}
async function sendToPort(data) {
if (port && port.writable) {
const writer = port.writable.getWriter();
const chars = new TextEncoder().encode(data);
portWritedChars += chars.length;
ioBuffer.push(chars, 'out');
await writer.write(chars);
writer.releaseLock();
}
}
function chageFontSize(delta) {
let fontSize = parseInt(inputFontSize.value, 10);
if (isNaN(fontSize)) {
fontSize = config.get('fontSize');
}
if (delta !== undefined) {
fontSize = delta < 0 ? fontSize + 1 : fontSize - 1;
}
fontSize = Math.max(10, Math.min(fontSize, 40));
inputFontSize.value = fontSize;
terminal.options.fontSize = fontSize;
config.set('fontSize', fontSize);
fitAddon.fit();
}
function changePortBaudrate() {
const baudRate = parseInt(selectSerialPortBaudrate.value, 10);
if (baudRate) {
config.set('baudRate', baudRate);
}
}
function highlightCell(event, state) {
const target = event.target;
if (lastHighlightIndex !== null) {
ioBuffer.highlightCell(lastHighlightIndex, false);
lastHighlightIndex = null;
}
if (target.tagName === 'DIV' && 'index' in target.dataset) {
const index = parseInt(target.dataset.index, 10);
ioBuffer.highlightCell(index, state);
lastHighlightIndex = state ? index : null;
}
}
function freeceCell(event) {
const target = event.target;
if (target.tagName === 'DIV' && 'index' in target.dataset) {
const index = parseInt(target.dataset.index, 10);
ioBuffer.freezeCellInfo(index);
}
}
function unfreeceCell(event) {
ioBuffer.unfreezeCellInfo();
highlightCell(event, true);
}
async function sendCtrlC() {
await sendToPort('\x03');
terminal.focus();
}
async function sendCtrlD() {
await sendToPort('\x04');
terminal.focus();
}
async function scrollToBottom() {
terminal.scrollToBottom();
terminal.focus();
}
async function resetStats() {
portReadedChars = 0;
portWritedChars = 0;
portLastReadedChars = 0;
portLastWritedChars = 0;
}
function updateDataBufferVisibility() {
dataTables.style.display = showDataBuffer ? 'flex' : 'none';
dataTableInfo.style.display = showDataBuffer ? 'flex' : 'none';
if (showDataBuffer) {
ioBuffer.redraw();
}
updateToolbar();
}
function toggleAboutVisibility() {
showAbout = !showAbout;
about.style.display = showAbout ? 'block' : 'none';
}
function toggleDataBufferVisibility() {
showDataBuffer = !showDataBuffer;
updateDataBufferVisibility();
}
function onWindowClick(event) {
if (showAbout && !about.contains(event.target) && !buttonShowAbout.contains(event.target)) {
toggleAboutVisibility();
}
}
function confirmExit() {
return "You have attempted to leave this page. Are you sure?";
}
async function readFromPort() {
const decoder = new TextDecoder('utf-8');
try {
reader = port.readable.getReader();
while (true) {
const { value, done } = await reader.read();
if (done) {
break;
}
if (value) {
ioBuffer.push(value, 'in');
portReadedChars += value.length;
const chars = decoder.decode(value, { stream: true });
terminal.write(chars);
}
}
} catch (err) {
console.error(err);
terminal.writeln(`Terminal error: reading from serial port.`);
} finally {
if (reader) {
reader.releaseLock();
}
disconnect();
}
}
async function connect() {
if (!port) {
try {
const baudRate = parseInt(selectSerialPortBaudrate.value, 10);
if (!baudRate) {
terminal.writeln('Terminal error: Invalid baudrate');
return;
}
port = await navigator.serial.requestPort();
await port.open({ baudRate });
terminal.reset();
terminal.focus();
portReadedChars = 0;
portWritedChars = 0;
updateToolbar();
readFromPort();
window.onbeforeunload = confirmExit;
port.addEventListener('disconnect', () => {
terminal.writeln('Terminal error: Serial port disconnected.');
disconnect();
});
} catch (err) {
console.error(err);
terminal.writeln(`Terminal error: Unable to connect to serial port.`);
}
} else {
disconnect();
}
}
async function disconnect() {
if (reader) {
try {
await reader.cancel();
} catch (error) {
console.error('Error canceling reader:', error);
}
reader = null;
}
if (port) {
try {
await port.close();
} catch (error) {
console.error('Error closing port:', error);
}
port = null;
}
portReadedChars = 0;
portWritedChars = 0;
document.title = 'WebSerial Terminal';
updateToolbar();
ioBuffer.reset();
window.onbeforeunload = null;
}
window.addEventListener('resize', () => fitAddon.fit());
window.addEventListener('click', onWindowClick);
terminalContainer.addEventListener('click', () => terminal.focus());
connectButton.addEventListener('click', () => connect());
buttonCtrlC.addEventListener('click', () => sendCtrlC());
buttonCtrlD.addEventListener('click', () => sendCtrlD());
buttonScrollToBottom.addEventListener('click', () => scrollToBottom());
buttonShowAbout.addEventListener('click', () => toggleAboutVisibility());
buttonShowBuffer.addEventListener('click', () => toggleDataBufferVisibility());
buttonResetStats.addEventListener('click', () => resetStats());
inputFontSize.addEventListener('change', () => chageFontSize());
selectSerialPortBaudrate.addEventListener('change', () => changePortBaudrate());
buttonFontSizeMinus.addEventListener('click', () => chageFontSize(1));
buttonFontSizePlus.addEventListener('click', () => chageFontSize(-1));
dataTableHex.addEventListener('mouseover', (event) => highlightCell(event, true));
dataTableHex.addEventListener('mouseout', (event) => highlightCell(event, false));
dataTableHex.addEventListener('dblclick', freeceCell);
dataTableHex.addEventListener('click', unfreeceCell);
dataTableAscii.addEventListener('mouseover', (event) => highlightCell(event, true));
dataTableAscii.addEventListener('mouseout', (event) => highlightCell(event, false));
inputFontSize.addEventListener('wheel', (event) => chageFontSize(event.deltaY), {
passive: false,
});
terminalContainer.addEventListener(
'wheel',
(event) => {
if (event.ctrlKey) {
event.preventDefault();
chageFontSize(event.deltaY);
}
},
{ passive: false }
);
updateDataBufferVisibility();
updateToolbar();
chageFontSize();
ioBuffer.cleanInfo();
ioBuffer.resize(terminalContainer.clientHeight);
app.style.visibility = 'visible';
setInterval(() => {
const connected = !!port;
svgToDevice.style.stroke = portWritedChars - portLastWritedChars > 0 ? '#aa1b1b' : '#313131';
svgFromDevice.style.stroke = portReadedChars - portLastReadedChars > 0 ? '#15aa00' : '#313131';
portLastReadedChars = portReadedChars;
portLastWritedChars = portWritedChars;
svgDevice.style.stroke = connected ? '#15aa00' : '#aa1b1b';
transferStats.textContent = `Read: ${portReadedChars} bytes, Written: ${portWritedChars} bytes`;
if (showDataBuffer) {
ioBuffer.redraw();
}
}, 250);
});

287
src/index.html Normal file
View File

@@ -0,0 +1,287 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@xterm/xterm@5.5.0/css/xterm.css"
/>
<link
rel="stylesheet"
href="./assets/css/styles.css"
/>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>WebSerial TERMINAL</title>
</head>
<body>
<div id="app">
<div id="top-bar">
<button
type="button"
id="button-connect"
class="toolbar-button toolbar-space corner"
>
Connect to Serial
</button>
<label
for="select-serial-port-baudrate"
class="toolbar-input-label"
>
Baudrate:
</label>
<select
id="select-serial-port-baudrate"
class="toolbar-select toolbar-space on-connected-disabled"
>
<option value="9600">9600</option>
<option value="19200">19200</option>
<option value="38400">38400</option>
<option value="57600">57600</option>
<option value="115200">115200</option>
<option value="230400">230400</option>
<option value="460800">460800</option>
<option value="921600">921600</option>
</select>
<label
for="input-font-size"
class="toolbar-input-label"
>
Font Size:
</label>
<div
id="button-font-size-minus"
class="toolbar-button corner"
>
&minus;
</div>
<input
id="input-font-size"
class="toolbar-input"
type="number"
min="10"
max="40"
/>
<div
id="button-font-size-plus"
class="toolbar-button toolbar-space"
>
&plus;
</div>
<div class="toolbar-spacer"></div>
<button
id="button-ctrl-c"
class="toolbar-button toolbar-space on-connected-show corner"
>
Ctrl+C
</button>
<button
type="button"
id="button-ctrl-d"
class="toolbar-button toolbar-space on-connected-show corner"
>
Ctrl+D
</button>
<button
type="button"
id="button-scroll-to-bottom"
class="toolbar-button on-connected-show corner"
>
Scroll to bottom
</button>
</div>
<div id="main">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 100 100"
class="terminal-background"
>
<text
id="terminal-background-text"
x="50%"
y="50%"
dominant-baseline="middle"
text-anchor="middle"
font-size="10"
fill="gray"
style="opacity: 0.1"
></text>
</svg>
<div id="terminal-container"></div>
</div>
<div id="data-table-info">
<div class="data-table-info-cell">
<div class="data-table-info-label">Locked</div>
<div class="data-table-info-value">
<svg
id="data-table-info-lock"
fill="red"
height="22px"
width="22px"
viewBox="0 0 330 330"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="m 65,325 h 200 c 8,0 15,-6 15,-15 v -170 c 0,-8 -6,-15 -15,-15 H 250 V 89 c 0,-46 -38,-85 -85,-85 -46,0 -85,38 -85,85 v 35 H 65 c -8,0 -15,6 -15,15 v 170 c 0,8 6,15 15,15 z m 117,-93 v 23 c 0,9 -8,17 -17,17 -9,0 -17,-7 -17,-17 V 232 C 139,227 135,218 135,209 c 0,-16 13,-29 29,-29 16,0 29,13 29,29 0,9 -4,17 -11,23 z M 110,89 c 0,-30 24,-55 55,-55 30,0 55,24 55,55 v 35 H 110 Z"
/>
</svg>
</div>
</div>
<div class="data-table-info-cell">
<div class="data-table-info-label">Direction</div>
<div
id="data-table-info-direction"
class="data-table-info-value"
></div>
</div>
<div class="data-table-info-cell">
<div class="data-table-info-label">HEX</div>
<div
id="data-table-info-hex"
class="data-table-info-value"
></div>
</div>
<div class="data-table-info-cell">
<div class="data-table-info-label">DEC</div>
<div
id="data-table-info-dec"
class="data-table-info-value"
></div>
</div>
<div class="data-table-info-cell">
<div class="data-table-info-label">BIN</div>
<div
id="data-table-info-bin"
class="data-table-info-value"
></div>
</div>
<div class="data-table-info-cell">
<div class="data-table-info-label">ASCII</div>
<div
id="data-table-info-ascii"
class="data-table-info-value"
></div>
</div>
<div class="data-table-info-cell">
<div class="data-table-info-label">Info</div>
<div
id="data-table-info-detail"
class="data-table-info-value"
></div>
</div>
</div>
<div id="data-tables">
<div id="data-table-hex"></div>
<div id="data-table-ascii"></div>
</div>
<div id="about">
WebSerial TERMINAL - <small>version 1.0.0</small><br /><br />
is a terminal emulator that allows you to connect to a serial device from your web browser.<br /><br />
Based on the
<a
href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API"
target="_blank"
>WebSerial API</a
>
and
<a
href="https://xtermjs.org/"
target="_blank"
>xterm.js</a
><br /><br />
Author:
<a
href="https://github.com/peterbay"
target=""
>Peter Bay</a
><br /><br />
Licence: MIT<br /><br />
Repository: Github -
<a
href="https://github.com/peterbay/webserial-terminal"
target="_blank"
>peterbay/webserial-terminal</a
>
</div>
<div id="bottom-bar">
<div class="toolbar-icons toolbar-space">
<svg
class="toolbar-svg-icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 400 400"
style="margin-top: -3px"
>
<style>
.cls-2 {
fill: none;
stroke: #313131;
stroke-width: 30;
stroke-linecap: round;
stroke-linejoin: round;
stroke-dasharray: none;
}
</style>
<g class="cls-2">
<path
d="M 170,116 H 283 V 63 l 95,94 -96,97 v -55 h -79"
id="svg-to-device"
/>
<path
d="M 228,283 H 117 V 336 L 20,241 117,145 v 53 h 85"
id="svg-from-device"
/>
</g>
</svg>
<svg
class="toolbar-svg-icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 400 400"
>
<g class="cls-2">
<path
d="M 155 66 L 155 112 L 155 66 z M 200 66 L 200 112 L 200 66 z M 245 66 L 245 112 L 245 66 z M 115 115 L 115 284 L 284 284 L 284 115 L 115 115 z M 66 153 L 112 153 L 66 153 z M 287 153 L 333 153 L 287 153 z M 66 198 L 112 198 L 66 198 z M 287 198 L 333 198 L 287 198 z M 66 243 L 112 243 L 66 243 z M 287 243 L 333 243 L 287 243 z M 155 286 L 155 333 L 155 286 z M 200 286 L 200 333 L 200 286 z M 245 286 L 245 333 L 245 286 z"
id="svg-device"
/>
</g>
</svg>
</div>
<span id="transfer-stats"></span>
<div class="toolbar-spacer"></div>
<button
type="button"
id="button-show-about"
class="toolbar-button corner toolbar-space"
>
About TERMINAL
</button>
<button
type="button"
id="button-reset-stats"
class="toolbar-button corner toolbar-space"
>
Reset Stats
</button>
<button
type="button"
id="button-show-buffer"
class="toolbar-button corner"
>
Show Buffer
</button>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/@xterm/xterm@5.5.0/lib/xterm.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-fit@0.10.0/lib/addon-fit.js"></script>
<script src="./assets/js/config.js"></script>
<script src="./assets/js/io-buffer.js"></script>
<script src="./assets/js/main.js"></script>
</body>
</html>

822
yarn.lock Normal file
View File

@@ -0,0 +1,822 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@eslint-community/eslint-utils@^4.2.0":
version "4.4.1"
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56"
integrity sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==
dependencies:
eslint-visitor-keys "^3.4.3"
"@eslint-community/regexpp@^4.12.1":
version "4.12.1"
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0"
integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==
"@eslint/config-array@^0.20.0":
version "0.20.0"
resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.20.0.tgz#7a1232e82376712d3340012a2f561a2764d1988f"
integrity sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==
dependencies:
"@eslint/object-schema" "^2.1.6"
debug "^4.3.1"
minimatch "^3.1.2"
"@eslint/config-helpers@^0.2.0":
version "0.2.1"
resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.2.1.tgz#26042c028d1beee5ce2235a7929b91c52651646d"
integrity sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==
"@eslint/core@^0.12.0":
version "0.12.0"
resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.12.0.tgz#5f960c3d57728be9f6c65bd84aa6aa613078798e"
integrity sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==
dependencies:
"@types/json-schema" "^7.0.15"
"@eslint/core@^0.13.0":
version "0.13.0"
resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.13.0.tgz#bf02f209846d3bf996f9e8009db62df2739b458c"
integrity sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==
dependencies:
"@types/json-schema" "^7.0.15"
"@eslint/eslintrc@^3.3.1":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.1.tgz#e55f7f1dd400600dd066dbba349c4c0bac916964"
integrity sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==
dependencies:
ajv "^6.12.4"
debug "^4.3.2"
espree "^10.0.1"
globals "^14.0.0"
ignore "^5.2.0"
import-fresh "^3.2.1"
js-yaml "^4.1.0"
minimatch "^3.1.2"
strip-json-comments "^3.1.1"
"@eslint/js@9.24.0":
version "9.24.0"
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.24.0.tgz#685277980bb7bf84ecc8e4e133ccdda7545a691e"
integrity sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==
"@eslint/object-schema@^2.1.6":
version "2.1.6"
resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f"
integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==
"@eslint/plugin-kit@^0.2.7":
version "0.2.8"
resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz#47488d8f8171b5d4613e833313f3ce708e3525f8"
integrity sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==
dependencies:
"@eslint/core" "^0.13.0"
levn "^0.4.1"
"@humanfs/core@^0.19.1":
version "0.19.1"
resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77"
integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==
"@humanfs/node@^0.16.6":
version "0.16.6"
resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.6.tgz#ee2a10eaabd1131987bf0488fd9b820174cd765e"
integrity sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==
dependencies:
"@humanfs/core" "^0.19.1"
"@humanwhocodes/retry" "^0.3.0"
"@humanwhocodes/module-importer@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==
"@humanwhocodes/retry@^0.3.0":
version "0.3.1"
resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a"
integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==
"@humanwhocodes/retry@^0.4.2":
version "0.4.2"
resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.2.tgz#1860473de7dfa1546767448f333db80cb0ff2161"
integrity sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==
"@jridgewell/gen-mapping@^0.3.5":
version "0.3.5"
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36"
integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==
dependencies:
"@jridgewell/set-array" "^1.2.1"
"@jridgewell/sourcemap-codec" "^1.4.10"
"@jridgewell/trace-mapping" "^0.3.24"
"@jridgewell/resolve-uri@^3.1.0":
version "3.1.2"
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6"
integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
"@jridgewell/set-array@^1.2.1":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280"
integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==
"@jridgewell/source-map@^0.3.3":
version "0.3.6"
resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a"
integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==
dependencies:
"@jridgewell/gen-mapping" "^0.3.5"
"@jridgewell/trace-mapping" "^0.3.25"
"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a"
integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==
"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25":
version "0.3.25"
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0"
integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==
dependencies:
"@jridgewell/resolve-uri" "^3.1.0"
"@jridgewell/sourcemap-codec" "^1.4.14"
"@types/estree@^1.0.6":
version "1.0.6"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==
"@types/json-schema@^7.0.15":
version "7.0.15"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
acorn-jsx@^5.3.2:
version "5.3.2"
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
acorn@^8.12.0:
version "8.14.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0"
integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==
acorn@^8.14.0:
version "8.14.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb"
integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==
acorn@^8.8.2:
version "8.13.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.13.0.tgz#2a30d670818ad16ddd6a35d3842dacec9e5d7ca3"
integrity sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==
ajv@^6.12.4:
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
dependencies:
fast-deep-equal "^3.1.1"
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
ansi-styles@^4.1.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
dependencies:
color-convert "^2.0.1"
argparse@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
axios@^1.8.4:
version "1.8.4"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.8.4.tgz#78990bb4bc63d2cae072952d374835950a82f447"
integrity sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==
dependencies:
follow-redirects "^1.15.6"
form-data "^4.0.0"
proxy-from-env "^1.1.0"
balanced-match@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
dependencies:
balanced-match "^1.0.0"
concat-map "0.0.1"
buffer-from@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
callsites@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
camel-case@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a"
integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==
dependencies:
pascal-case "^3.1.2"
tslib "^2.0.3"
chalk@^4.0.0:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
dependencies:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
clean-css@~5.3.2:
version "5.3.3"
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.3.tgz#b330653cd3bd6b75009cc25c714cae7b93351ccd"
integrity sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==
dependencies:
source-map "~0.6.0"
color-convert@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
dependencies:
color-name "~1.1.4"
color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
combined-stream@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
dependencies:
delayed-stream "~1.0.0"
commander@^10.0.0:
version "10.0.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==
commander@^2.20.0:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
cross-spawn@^7.0.6:
version "7.0.6"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
dependencies:
path-key "^3.1.0"
shebang-command "^2.0.0"
which "^2.0.1"
debug@^4.3.1, debug@^4.3.2:
version "4.3.7"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52"
integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==
dependencies:
ms "^2.1.3"
deep-is@^0.1.3:
version "0.1.4"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
dot-case@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751"
integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==
dependencies:
no-case "^3.0.4"
tslib "^2.0.3"
entities@^4.4.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
escape-string-regexp@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
eslint-scope@^8.3.0:
version "8.3.0"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.3.0.tgz#10cd3a918ffdd722f5f3f7b5b83db9b23c87340d"
integrity sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==
dependencies:
esrecurse "^4.3.0"
estraverse "^5.2.0"
eslint-visitor-keys@^3.4.3:
version "3.4.3"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
eslint-visitor-keys@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz#1f785cc5e81eb7534523d85922248232077d2f8c"
integrity sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==
eslint-visitor-keys@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45"
integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==
eslint@^9.24.0:
version "9.24.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.24.0.tgz#9a7f2e6cb2de81c405ab244b02f4584c79dc6bee"
integrity sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==
dependencies:
"@eslint-community/eslint-utils" "^4.2.0"
"@eslint-community/regexpp" "^4.12.1"
"@eslint/config-array" "^0.20.0"
"@eslint/config-helpers" "^0.2.0"
"@eslint/core" "^0.12.0"
"@eslint/eslintrc" "^3.3.1"
"@eslint/js" "9.24.0"
"@eslint/plugin-kit" "^0.2.7"
"@humanfs/node" "^0.16.6"
"@humanwhocodes/module-importer" "^1.0.1"
"@humanwhocodes/retry" "^0.4.2"
"@types/estree" "^1.0.6"
"@types/json-schema" "^7.0.15"
ajv "^6.12.4"
chalk "^4.0.0"
cross-spawn "^7.0.6"
debug "^4.3.2"
escape-string-regexp "^4.0.0"
eslint-scope "^8.3.0"
eslint-visitor-keys "^4.2.0"
espree "^10.3.0"
esquery "^1.5.0"
esutils "^2.0.2"
fast-deep-equal "^3.1.3"
file-entry-cache "^8.0.0"
find-up "^5.0.0"
glob-parent "^6.0.2"
ignore "^5.2.0"
imurmurhash "^0.1.4"
is-glob "^4.0.0"
json-stable-stringify-without-jsonify "^1.0.1"
lodash.merge "^4.6.2"
minimatch "^3.1.2"
natural-compare "^1.4.0"
optionator "^0.9.3"
espree@^10.0.1:
version "10.2.0"
resolved "https://registry.yarnpkg.com/espree/-/espree-10.2.0.tgz#f4bcead9e05b0615c968e85f83816bc386a45df6"
integrity sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==
dependencies:
acorn "^8.12.0"
acorn-jsx "^5.3.2"
eslint-visitor-keys "^4.1.0"
espree@^10.3.0:
version "10.3.0"
resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a"
integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==
dependencies:
acorn "^8.14.0"
acorn-jsx "^5.3.2"
eslint-visitor-keys "^4.2.0"
esquery@^1.5.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7"
integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==
dependencies:
estraverse "^5.1.0"
esrecurse@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
dependencies:
estraverse "^5.2.0"
estraverse@^5.1.0, estraverse@^5.2.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
esutils@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
fast-json-stable-stringify@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
fast-levenshtein@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
file-entry-cache@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f"
integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==
dependencies:
flat-cache "^4.0.0"
find-up@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
dependencies:
locate-path "^6.0.0"
path-exists "^4.0.0"
flat-cache@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c"
integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==
dependencies:
flatted "^3.2.9"
keyv "^4.5.4"
flatted@^3.2.9:
version "3.3.1"
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a"
integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==
follow-redirects@^1.15.6:
version "1.15.9"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1"
integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==
form-data@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.1.tgz#ba1076daaaa5bfd7e99c1a6cb02aa0a5cff90d48"
integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"
glob-parent@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
dependencies:
is-glob "^4.0.3"
globals@^14.0.0:
version "14.0.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e"
integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==
has-flag@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
html-minifier-terser@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz#18752e23a2f0ed4b0f550f217bb41693e975b942"
integrity sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==
dependencies:
camel-case "^4.1.2"
clean-css "~5.3.2"
commander "^10.0.0"
entities "^4.4.0"
param-case "^3.0.4"
relateurl "^0.2.7"
terser "^5.15.1"
ignore@^5.2.0:
version "5.3.2"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==
import-fresh@^3.2.1:
version "3.3.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
dependencies:
parent-module "^1.0.0"
resolve-from "^4.0.0"
imurmurhash@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
is-extglob@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
is-glob@^4.0.0, is-glob@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
dependencies:
is-extglob "^2.1.1"
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
js-yaml@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
dependencies:
argparse "^2.0.1"
json-buffer@3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
json-schema-traverse@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
json-stable-stringify-without-jsonify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==
keyv@^4.5.4:
version "4.5.4"
resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93"
integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==
dependencies:
json-buffer "3.0.1"
levn@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==
dependencies:
prelude-ls "^1.2.1"
type-check "~0.4.0"
locate-path@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
dependencies:
p-locate "^5.0.0"
lodash.merge@^4.6.2:
version "4.6.2"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
lower-case@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28"
integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==
dependencies:
tslib "^2.0.3"
mime-db@1.52.0:
version "1.52.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
mime-types@^2.1.12:
version "2.1.35"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
dependencies:
mime-db "1.52.0"
minimatch@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
dependencies:
brace-expansion "^1.1.7"
ms@^2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
no-case@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d"
integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==
dependencies:
lower-case "^2.0.2"
tslib "^2.0.3"
optionator@^0.9.3:
version "0.9.4"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734"
integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==
dependencies:
deep-is "^0.1.3"
fast-levenshtein "^2.0.6"
levn "^0.4.1"
prelude-ls "^1.2.1"
type-check "^0.4.0"
word-wrap "^1.2.5"
p-limit@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
dependencies:
yocto-queue "^0.1.0"
p-locate@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
dependencies:
p-limit "^3.0.2"
param-case@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5"
integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==
dependencies:
dot-case "^3.0.4"
tslib "^2.0.3"
parent-module@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
dependencies:
callsites "^3.0.0"
pascal-case@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb"
integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==
dependencies:
no-case "^3.0.4"
tslib "^2.0.3"
path-exists@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
path-key@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
prelude-ls@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
proxy-from-env@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
punycode@^2.1.0:
version "2.3.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
relateurl@^0.2.7:
version "0.2.7"
resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==
resolve-from@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
shebang-command@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
dependencies:
shebang-regex "^3.0.0"
shebang-regex@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
source-map-support@~0.5.20:
version "0.5.21"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
dependencies:
buffer-from "^1.0.0"
source-map "^0.6.0"
source-map@^0.6.0, source-map@~0.6.0:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
strip-json-comments@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
supports-color@^7.1.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
dependencies:
has-flag "^4.0.0"
terser@^5.15.1:
version "5.36.0"
resolved "https://registry.yarnpkg.com/terser/-/terser-5.36.0.tgz#8b0dbed459ac40ff7b4c9fd5a3a2029de105180e"
integrity sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==
dependencies:
"@jridgewell/source-map" "^0.3.3"
acorn "^8.8.2"
commander "^2.20.0"
source-map-support "~0.5.20"
tslib@^2.0.3:
version "2.8.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.0.tgz#d124c86c3c05a40a91e6fdea4021bd31d377971b"
integrity sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==
type-check@^0.4.0, type-check@~0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==
dependencies:
prelude-ls "^1.2.1"
uri-js@^4.2.2:
version "4.4.1"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
dependencies:
punycode "^2.1.0"
which@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
dependencies:
isexe "^2.0.0"
word-wrap@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==