Compare commits

...

2 Commits

Author SHA1 Message Date
fdbb661c17 Added terminal client 2023-05-12 20:59:45 +02:00
4e891ce3a4 Added JS client 2023-05-12 20:58:50 +02:00
18 changed files with 1993 additions and 1 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/target

23
Cargo.lock generated
View File

@@ -723,6 +723,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"tide", "tide",
"tide-tracing",
"tide-websockets", "tide-websockets",
"tokio", "tokio",
"tokio-stream", "tokio-stream",
@@ -2063,6 +2064,18 @@ dependencies = [
"serde_json", "serde_json",
] ]
[[package]]
name = "tide-tracing"
version = "0.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "500f567f8c4d65210e6a7c9978661cc7ad6be1dc97e32c3e88bf8f0f0599c23d"
dependencies = [
"async-trait",
"tide",
"tracing",
"tracing-futures",
]
[[package]] [[package]]
name = "tide-websockets" name = "tide-websockets"
version = "0.4.0" version = "0.4.0"
@@ -2242,6 +2255,16 @@ dependencies = [
"tracing-subscriber 0.1.6", "tracing-subscriber 0.1.6",
] ]
[[package]]
name = "tracing-futures"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
dependencies = [
"pin-project",
"tracing",
]
[[package]] [[package]]
name = "tracing-log" name = "tracing-log"
version = "0.1.3" version = "0.1.3"

15
d3270console/Cargo.toml Normal file
View File

@@ -0,0 +1,15 @@
[package]
name = "d3270console"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = { version = "1.28.1", features = ["full"] }
crossterm = { version = "0.26.1", features = ["event-stream"] }
d3270-common = {path = "../d3270-common"}
serde_json = "1.0.96"
structopt = "0.3.26"
anyhow = "1.0.71"
futures = "0.3.28"

390
d3270console/src/main.rs Normal file
View File

@@ -0,0 +1,390 @@
use std::fmt::Debug;
use std::io;
use std::io::Write;
use std::net::SocketAddr;
use std::ops::Range;
use std::os::linux::raw::stat;
use crossterm::{Command, cursor, queue, style, terminal};
use crossterm::event::{Event, EventStream, KeyCode, KeyEvent, KeyModifiers};
use crossterm::style::{Attribute};
use crossterm::terminal::ClearType;
use futures::StreamExt;
use tokio::net::TcpStream;
use structopt::StructOpt;
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
use tokio::select;
use d3270_common::b3270;
use d3270_common::b3270::{Indication, Operation};
use d3270_common::b3270::indication::{Connection, ConnectionState, Cursor, Erase, Screen};
use d3270_common::b3270::operation::{Action, Run};
use d3270_common::b3270::types::{Color, GraphicRendition, PackedAttr};
use d3270_common::b3270::types::Color::{NeutralBlack, NeutralWhite};
use d3270_common::tracker::Tracker;
macro_rules! actions {
($($aid:ident ( $($arg:expr),* $(,)?) ),+ $(,)?)=> {
vec![
$(
Action{
action: stringify!($aid ).to_owned(),
args: vec![$($arg.to_string()),*]
}
),+
]
}
}
#[derive(StructOpt)]
struct Opts {
host: SocketAddr,
}
#[derive(Default)]
pub struct State {
tracker: Tracker,
// cols, rows
screen_size: (u16, u16),
}
trait IfElse {
fn if_else<T>(&self, if_t: T, if_f: T) -> T;
}
impl IfElse for bool {
fn if_else<T>(&self, if_t: T, if_f: T) -> T {
if *self { if_t } else { if_f }
}
}
fn debug_style<C: crossterm::Command+Debug>(styl: C) -> C {
// eprintln!("styl: {styl:?}");
// let mut rbuf = String::new();
// styl.write_ansi(&mut rbuf).ok();
// eprintln!("rendered: {:?}", rbuf);
styl
}
impl State {
fn apply_indicator(&mut self, mut ind: Indication) -> io::Result<()> {
self.tracker.handle_indication(&mut ind);
let mut buf = Vec::new();
queue!(buf, crossterm::terminal::BeginSynchronizedUpdate)?;
let empty_buf = buf.len();
match ind {
Indication::Oia(_) |
Indication::Connection(_) |
Indication::Initialize(_) => self.redraw_all()?,
Indication::Screen(Screen{rows, ..}) => {
for row in rows {
let row_n = row.row as usize - 1;
for upd in row.changes {
let col = upd.column as usize - 1;
let ncols = upd.change.len();
self.redraw_region(&mut buf, row_n, col..col+ncols)?;
}
}
self.redraw_oia(&mut buf)?;
self.restore_cursor(&mut buf)?;
}
Indication::Erase(_) | Indication::ScreenMode(_) => {
self.redraw_all()?; // this does its own writing
}
_ => {},
}
if buf.len() > empty_buf {
queue!(buf, crossterm::terminal::EndSynchronizedUpdate)?;
io::stdout().write_all(buf.as_slice())?;
io::stdout().flush()?;
}
Ok(())
}
fn redraw_all(&self) -> io::Result<()> {
let mut buf = Vec::new();
queue!(buf,
crossterm::terminal::BeginSynchronizedUpdate,
style::SetBackgroundColor(style::Color::Rgb {r: 20, g: 20, b: 20}),
terminal::Clear(ClearType::All),
)?;
let screen_len = self.tracker.get_screen().len();
let screen_width = self.tracker.get_screen()[0].len();
for i in 0..screen_len {
self.redraw_region(&mut buf, i, 0..screen_width)?;
}
self.redraw_oia(&mut buf)?;
queue!(buf, crossterm::terminal::EndSynchronizedUpdate)?;
io::stdout().write_all(buf.as_slice())?;
io::stdout().flush()?;
Ok(())
}
fn redraw_oia(&self, buf: &mut Vec<u8>) -> io::Result<()> {
let screen_len = self.screen_size.1;
let pos = match self.tracker.get_cursor() {
Cursor { enabled: false, .. } => " -/- ".to_owned(),
Cursor { enabled: true, row: Some(r), column: Some(c) } =>
format!("{:3}/{:-3}", r-1, c-1),
Cursor { enabled: true, row: None, column: Some(c) } =>
format!("---/{:-3}", c-1),
Cursor { enabled: true, row: Some(r), column: None } =>
format!("{:3}/---", r-1),
Cursor { enabled: true, row: None, column: None } => "---/---".to_owned(),
};
queue!(buf,
cursor::MoveTo(1, screen_len-1),
style::SetStyle(style::ContentStyle{
foreground_color: Some(style::Color::Blue),
background_color: Some(style::Color::Black),
attributes: Attribute::OverLined.into(),
underline_color: Some(style::Color::Cyan),
}),
)?;
// print the OIA contents...
let oia = self.tracker.get_oia_state();
let status = if let Some(ref lock) = self.tracker.get_oia_state().lock {
lock.as_str()
} else {
""
};
let conn_ch = match self.tracker.get_connection().state {
ConnectionState::NotConnected => " ",
ConnectionState::Reconnecting => "~",
ConnectionState::Resolving => "?",
ConnectionState::TcpPending => ".",
ConnectionState::TlsPending => "_",
ConnectionState::TelnetPending => "t",
ConnectionState::ConnectedNvt => "n",
ConnectionState::ConnectedNvtCharmode => "C",
ConnectionState::Connected3270 => "3",
ConnectionState::ConnectedUnbound => "!",
ConnectionState::ConnectedENvt => "N",
ConnectionState::ConnectedSscp => "S",
ConnectionState::ConnectedTn3270e => "E",
};
write!(
buf,
" {undera}{conn_ch}{status:-35} {compose:10}{ta}{rm}{im}{pr}{st}{sc} {lu:8} {timing:7} {pos} ",
undera = oia.not_undera.if_else('B', ' '),
compose = match oia.compose {
Some((ty, ref ch)) => format!("{ty:3?} {ch:6}"),
None => "".to_owned(),
},
ta = oia.typeahead.if_else('T', ' '),
rm = oia.reverse_input.if_else('R', ' '),
im = oia.reverse_input.if_else('^', ' '),
pr = oia.printer_lu.is_some().if_else('P', ' '),
// security?
st = oia.screen_trace.is_some().if_else('t', ' '),
sc = oia.script.if_else('s', ' '),
lu = oia.lu.as_ref().map(String::as_str).unwrap_or(""),
timing = oia.timing.as_ref().map(String::as_str).unwrap_or(""),
)?;
queue!(buf,
crossterm::terminal::Clear(crossterm::terminal::ClearType::UntilNewLine),
crossterm::style::SetAttribute(Attribute::Reset)
)?;
self.restore_cursor(buf)
}
fn restore_cursor(&self, buf: &mut Vec<u8>) -> io::Result<()> {
match self.tracker.get_cursor() {
Cursor { enabled: true, row: Some(row), column: Some(col)} => {
queue!(buf,
crossterm::cursor::MoveTo(*col as u16, *row as u16),
crossterm::cursor::Show,
)
}
_ => queue!(buf, crossterm::cursor::Hide)
}
}
fn redraw_region(&self, buf: &mut Vec<u8>, row: usize, cols: Range<usize>) -> io::Result<()> {
queue!(buf, cursor::MoveTo(cols.start as u16 + 1, row as u16 + 1)).ok();
let mut last_attr = u32::c_pack(Color::NeutralWhite, Color::NeutralBlack, GraphicRendition::empty());
for chr in &self.tracker.get_screen()[row][cols] {
if chr.attr != last_attr {
// eprintln!("chattr: {:08x}", chr.attr);
queue!(buf,
style::SetAttribute(Attribute::Reset),
debug_style(style::SetForegroundColor(color_from_3270(chr.attr.c_fg()))),
// style::SetBackgroundColor(color_from_3270(chr.attr.c_bg())),
)?;
let c_gr = chr.attr.c_gr();
for (gr, attr) in GR_TO_ATTR {
if c_gr.contains(*gr) {
queue!(buf, style::SetAttribute(*attr))?;
}
}
last_attr = chr.attr;
}
write!(buf, "{}", chr.ch)?;
}
queue!(buf, style::SetAttribute(Attribute::Reset))?;
Ok(())
}
}
static GR_TO_ATTR: &[(GraphicRendition, Attribute)] = &[
(GraphicRendition::BLINK, Attribute::SlowBlink),
(GraphicRendition::HIGHLIGHT, Attribute::Italic),
(GraphicRendition::REVERSE, Attribute::Reverse),
(GraphicRendition::ORDER, Attribute::Dim),
];
fn color_from_3270(color: b3270::types::Color) -> crossterm::style::Color {
use crossterm::style::Color as CtColor;
// TODO: make these RGB
match color {
Color::NeutralBlack => CtColor::Black,
Color::Blue => CtColor::Blue,
Color::Red => CtColor::Red,
Color::Pink => CtColor::Magenta,
Color::Green => CtColor::DarkGreen,
Color::Turquoise => CtColor::Cyan,
Color::Yellow => CtColor::Yellow,
Color::NeutralWhite => CtColor::White,
Color::Black => CtColor::Black,
Color::DeepBlue => CtColor::DarkBlue,
Color::Orange => CtColor::DarkYellow,
Color::Purple => CtColor::DarkMagenta,
Color::PaleGreen => CtColor::Green,
Color::PaleTurquoise => CtColor::Cyan,
Color::Gray => CtColor::Grey,
Color::White => CtColor::White,
}
}
mod term {
use std::io;
use std::io::Write;
use crossterm::queue;
pub struct TermSetup(bool);
impl TermSetup {
pub fn setup() -> io::Result<Self> {
let mut stdout = io::stdout();
queue!(stdout,
crossterm::terminal::EnterAlternateScreen,
crossterm::terminal::DisableLineWrap,
crossterm::terminal::Clear(crossterm::terminal::ClearType::All),
)?;
stdout.flush()?;
crossterm::terminal::enable_raw_mode()?;
Ok(Self(false))
}
pub fn shutdown(&mut self) -> io::Result<()> {
if self.0 { return Ok(()); }
let mut stdout = io::stdout();
crossterm::terminal::disable_raw_mode()?;
queue!(stdout,
crossterm::terminal::Clear(crossterm::terminal::ClearType::All),
crossterm::terminal::LeaveAlternateScreen,
crossterm::terminal::EnableLineWrap,
)?;
stdout.flush()?;
// avoid being called again in drop.
self.0 = true;
Ok(())
}
}
impl Drop for TermSetup {
fn drop(&mut self) {
self.shutdown().ok();
}
}
}
use term::TermSetup;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let mut log_f = std::fs::File::create("b3270.trace.jsonl")?;
let opts = Opts::from_args();
let size = crossterm::terminal::size()?;
let mut term_setup = TermSetup::setup()?;
let mut remote = TcpStream::connect(opts.host).await?;
let (rem_rd, mut rem_wr) = remote.split();
let mut rem_rd = BufReader::new(rem_rd).lines();
let mut state = State{
tracker: Default::default(),
screen_size: size,
};
state.apply_indicator(Indication::Connection(Connection{state: ConnectionState::NotConnected, host: None, cause: None}))?;
let mut input = EventStream::new();
'main: loop {
select! {
evt = rem_rd.next_line() => {
let evt = if let Some(evt) = evt? { evt } else { break 'main; };
log_f.write_all(evt.as_bytes())?;
log_f.write_all(b"\n")?;
let ind = match serde_json::from_str(evt.as_str()) {
Ok(ind) => ind,
Err(err) => {
term_setup.shutdown()?;
eprintln!("Error: {err:?}");
return Err(err.into());
}
};
state.apply_indicator(ind)?;
},
evt = input.next() => {
let evt = if let Some(evt) = evt { evt } else { break 'main; };
match evt? {
Event::Key(KeyEvent{code, modifiers, ..}) => {
let actions = match (code, modifiers) {
(KeyCode::Char('c'), KeyModifiers::CONTROL) => break 'main,
(KeyCode::Char(ch), KeyModifiers::NONE) => actions![Key(ch)],
(KeyCode::Char(ch), KeyModifiers::SHIFT) if ch.is_alphabetic() => actions![Key(ch.to_uppercase())],
(KeyCode::Backspace, _) => actions![BackSpace()],
(KeyCode::Enter, _) => actions![Enter()],
(KeyCode::F(n), KeyModifiers::NONE) => actions!(PF(n)),
(KeyCode::F(n), KeyModifiers::SHIFT) => actions!(PF(n+12)),
(KeyCode::Char('r'), KeyModifiers::CONTROL) => actions!(Reset()),
(KeyCode::Esc, KeyModifiers::NONE) => actions!(Attn()),
(KeyCode::Tab, KeyModifiers::NONE) => actions!(Tab()),
(KeyCode::Tab, KeyModifiers::SHIFT) |
(KeyCode::BackTab, _) => actions!(BackTab()),
(KeyCode::End, KeyModifiers::CONTROL) => actions!(EraseEOF()),
(KeyCode::Delete, KeyModifiers::NONE) => actions!(Delete()),
(KeyCode::Up, KeyModifiers::NONE) => actions!(Up()),
(KeyCode::Down, KeyModifiers::NONE) => actions!(Down()),
(KeyCode::Left, KeyModifiers::NONE) => actions!(Left()),
(KeyCode::Right, KeyModifiers::NONE) => actions!(Right()),
(KeyCode::PageUp, KeyModifiers::NONE) => actions!(Scroll("backward")),
(KeyCode::PageDown, KeyModifiers::NONE) => actions!(Scroll("forward")),
(KeyCode::Char('l'), KeyModifiers::CONTROL) => {
state.redraw_all()?;
continue 'main;
}
(_, _) => {
eprintln!("key {code:?} {modifiers:?}");
continue 'main;
},
};
let op = Operation::Run(Run{actions, type_: None, r_tag: None});
let mut enc = serde_json::to_string(&op)?;
enc.push('\n');
rem_wr.write_all(enc.as_bytes()).await?;
}
Event::Mouse(_) => {}
Event::Paste(_) => {}
Event::Resize(_, _) => {}
_ => {}
}
}
}
}
term_setup.shutdown()?;
Ok(())
}

View File

@@ -12,6 +12,7 @@ anyhow = "1.0.71"
tokio = { version = "1.28.0", features = ["full"] } tokio = { version = "1.28.0", features = ["full"] }
tide = "0.16.0" tide = "0.16.0"
tide-websockets = "0.4.0" tide-websockets = "0.4.0"
tide-tracing = "0.0.12"
d3270-common = {path = "../d3270-common"} d3270-common = {path = "../d3270-common"}
bytes = "1.4.0" bytes = "1.4.0"
tracing = "0.1.37" tracing = "0.1.37"

View File

@@ -18,6 +18,7 @@ use d3270_common::b3270::operation::Action;
pub mod arbiter; pub mod arbiter;
pub mod gen_connection; pub mod gen_connection;
pub mod tcp_server; pub mod tcp_server;
pub mod ws_server;
struct TaggedJoinHandle { struct TaggedJoinHandle {
handle: JoinHandle<anyhow::Error>, handle: JoinHandle<anyhow::Error>,
@@ -65,6 +66,7 @@ async fn main() -> anyhow::Result<()> {
let mut args_iter = std::env::args_os().peekable(); let mut args_iter = std::env::args_os().peekable();
let mut connect_str = None; let mut connect_str = None;
let mut tcp_listen = None; let mut tcp_listen = None;
let mut http_listen = None;
args_iter.next(); // skip program name. args_iter.next(); // skip program name.
@@ -94,7 +96,17 @@ async fn main() -> anyhow::Result<()> {
.map_err(|_| anyhow!("Failed to parse tcp-listen address"))? .map_err(|_| anyhow!("Failed to parse tcp-listen address"))?
.parse() .parse()
.map(Some) .map(Some)
.map_err(|_| anyhow!("Invalid listen address"))?; .map_err(|_| anyhow!("Failed to parse tcp-listen address"))?;
}
"-http-listen" => {
http_listen = args_iter
.next()
.ok_or_else(|| anyhow!("Arg required for -http-listen"))?
.into_string()
.map_err(|_| anyhow!("Failed to parse http-listen address"))?
.parse()
.map(Some)
.map_err(|_| anyhow!("Failed to parse http-listen address"))?;
} }
"-e" => { "-e" => {
'skip: while let Some(arg) = args_iter.peek() { 'skip: while let Some(arg) = args_iter.peek() {
@@ -131,6 +143,10 @@ async fn main() -> anyhow::Result<()> {
let tcp_listener = tcp_server::listener_proc(addr, arbiter_req.clone()).await?; let tcp_listener = tcp_server::listener_proc(addr, arbiter_req.clone()).await?;
handles.push(tcp_listener.tagged("tcp_listener")); handles.push(tcp_listener.tagged("tcp_listener"));
} }
if let Some(addr) = http_listen {
let ws_listener = ws_server::start_ws_server(addr, arbiter_req.clone()).await?;
handles.push(ws_listener.tagged("ws_server"));
}
let ((source, error), _, _) = select_all(handles).await; let ((source, error), _, _) = select_all(handles).await;
error!(source, %error, "A core task failed"); error!(source, %error, "A core task failed");

53
d3270d/src/ws_server.rs Normal file
View File

@@ -0,0 +1,53 @@
use std::net::SocketAddr;
use anyhow::anyhow;
use tide::prelude::*;
use tide::Request;
use tide_websockets::{WebSocketConnection, self as ws};
use tokio::select;
use tokio::task::JoinHandle;
use crate::arbiter::ArbiterHandleRequester;
use crate::gen_connection::GenConnection;
use futures::stream::StreamExt;
use tracing::{info, warn};
use d3270_common::b3270::Indication;
pub async fn start_ws_server(socket: SocketAddr, handle_requester: ArbiterHandleRequester, ) -> anyhow::Result<JoinHandle<anyhow::Error>> {
let mut app = tide::Server::with_state(handle_requester);
app.with(tide_tracing::TraceMiddleware::new());
app.at("/api/ws").get(tide_websockets::WebSocket::new(handle_websocket));
let mut listener = app.bind(socket.clone()).await?;
Ok(tokio::task::spawn(async move {
info!(%socket, "Starting HTTP server");
listener.accept().await
.map(|()| anyhow!("HTTP server returned early"))
.unwrap_or_else(Into::into)
}))
}
async fn handle_websocket(req: Request<ArbiterHandleRequester>, mut ws: WebSocketConnection) -> tide::Result<()> {
let mut arbiter = GenConnection::new(req.state().clone()).await?;
// TODO: do authenticatey things
'main: loop {
select! {
msg = ws.next() => {
let msg: ws::Message = if let Some(msg) = msg { msg? } else { break 'main; };
match msg {
ws::Message::Text(text) => arbiter.handle_client_line(text).await?,
ws::Message::Binary(_) => warn!("Unexpected binary message from client"),
ws::Message::Ping(data) => ws.send(ws::Message::Pong(data)).await?,
ws::Message::Close(_) => break 'main,
_ => (),
}
},
msg = arbiter.next_indication() => {
let msg: Indication = if let Some(msg) = msg { msg } else { break 'main; };
ws.send_json(&msg).await?;
}
}
}
Ok(())
}

24
js3270/.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

3
js3270/.postcssrc.yml Normal file
View File

@@ -0,0 +1,3 @@
plugins:
postcss-simple-vars: {}
postcss-preset-env: {}

14
js3270/index.html Normal file
View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<!-- link rel="stylesheet" type="text/css" href="src/style.css" / -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>3270 Console</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

17
js3270/package.json Normal file
View File

@@ -0,0 +1,17 @@
{
"name": "js3270",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview"
},
"devDependencies": {
"typescript": "^5.0.2",
"vite": "^4.3.2",
"postcss-preset-env": "^8.3.2",
"postcss-simple-vars": "^7.0.1"
}
}

1
js3270/public/vite.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

246
js3270/src/main.ts Normal file
View File

@@ -0,0 +1,246 @@
import './style.css'
import typescriptLogo from './typescript.svg'
import viteLogo from '/vite.svg'
import {Action, Color, Cursor, IndErase, Indication, IndScreen, InitializeIndication, Operation} from "./suite3270.ts";
type GrElement = "underline" | "blink" | "highlight" | "selectable" | "reverse" | "wide" | "order" | "private-use" | "no-copy" | "wrap";
class CharCell {
td: HTMLElement
char: string
fg: Color
bg: Color
gr: Set<GrElement>
constructor(td: HTMLElement) {
this.td = td;
this.char = ' ';
this.fg = "neutralWhite";
this.bg = "neutralBlack";
this.gr = new Set<GrElement>();
}
update() {
let cell = this;
let grset = [];
for (let grattr of cell.gr) {
grset.push(grattr);
}
cell.td.dataset.gr = grset.join(" ");
cell.td.dataset.fg = cell.fg;
cell.td.dataset.bg = cell.bg;
cell.td.replaceChildren(cell.char)
}
}
class Js3270 {
private character_tbl: HTMLTableElement;
private cgrid: CharCell[][];
private oia_row: HTMLDivElement;
private ws: WebSocket;
private def_fg: Color;
private def_bg: Color;
private cursor: Cursor;
private cursor_cell: CharCell|null;
constructor(root: HTMLDivElement) {
// set up default properties
this.def_fg = "neutralWhite";
this.def_bg = "neutralBlack";
this.character_tbl = document.createElement("table");
this.character_tbl.className = "cgrid";
this.cursor = {enabled: true, row: 1, column: 1};
this.cursor_cell = null;
this.cgrid = [];
this.oia_row = document.createElement("div");
// TODO: make this lookup the address based on where it's loaded from
this.ws = new WebSocket("ws://127.0.0.1:13270/api/ws");
this.ws.addEventListener("message", this.on_message.bind(this))
root.replaceChildren(this.character_tbl, this.oia_row);
window.addEventListener("keydown", this.on_keydown.bind(this))
}
private send(actions: Action[]) {
let op: Operation = {run: {actions: actions}};
this.ws.send(JSON.stringify(op));
}
private keymap: {[k: string]: [string, string[]]} = {
"PageUp": ["Scroll", ["backward"]],
"PageDown": ["Scroll", ["forward"]],
"Backspace": ["Backspace", []],
"Enter": ["Enter", []],
"Tab": ["Tab", []],
"S+Tab": ["Backtab", []],
"ArrowUp": ["Up", []],
"ArrowDown": ["Down", []],
"ArrowRight": ["Right", []],
"ArrowLeft": ["Left", []],
"M+r": ["Reset", []],
"M+a": ["Attn", []],
}
private on_keydown(evt: KeyboardEvent) {
let key_str = [
evt.ctrlKey? "C+":"",
evt.altKey?"M+":"",
evt.shiftKey?"S+":"",
evt.key
].join("");
if (evt.key.length == 1 && !evt.altKey) {
this.send([{action: "Key", args: [evt.key]}]);
evt.stopPropagation();
return;
} else if (key_str in this.keymap) {
let [action, args] = this.keymap[key_str];
this.send([{action, args}]);
evt.preventDefault();
evt.stopPropagation();
} else if (evt.key[0] == "F" && evt.key.substring(1).match("[0-9]+")) {
let fn = evt.key.substring(1);
if (evt.shiftKey) {
fn = ((fn as any - 0) + 13) + "";
}
this.send([{action: "PF", args: [fn]}]);
evt.stopImmediatePropagation();
evt.stopPropagation();
evt.preventDefault();
} else {
console.log(key_str);
}
}
private handle_indication(ind: Indication | InitializeIndication) {
if ("initialize" in ind) {
for (let subind of ind.initialize) {
this.handle_indication(subind);
}
} else if ("screen-mode" in ind) {
let mode = ind["screen-mode"];
this.resize_screen(mode.rows, mode.columns);
} else if ("screen" in ind) {
this.handle_ind_screen(ind.screen)
} else if ("erase" in ind) {
this.handle_ind_erase(ind.erase);
}
}
private resize_screen(rows: number, columns: number) {
this.cgrid = [];
let tbody = document.createElement("tbody");
for (let y = 0; y < rows; y++) {
let row: CharCell[] = [];
let tr = document.createElement("tr");
for (let x = 0; x < columns; x++) {
let td = document.createElement("td");
let cc = new CharCell(td);
cc.fg = this.def_fg;
cc.bg = this.def_bg;
row.push(cc);
tr.append(td);
}
tbody.append(tr);
this.cgrid.push(row);
}
this.redraw_screen();
this.character_tbl.replaceChildren(tbody);
}
private on_message(ev: MessageEvent<any>) {
let ind = JSON.parse(ev.data) as Indication;
this.handle_indication(ind);
// console.log(ind);
}
private redraw_screen() {
for (let row of this.cgrid) {
for (let cell of row) {
cell.update()
}
}
this.move_cursor();
}
private redraw_region(row: number, col_start: number, count: number) {
let c_row = this.cgrid[row];
for (let i = col_start; i < col_start + count; i++) {
c_row[i].update()
}
}
private move_cursor() {
if (this.cursor_cell) {
delete this.cursor_cell.td.dataset.cursor;
this.cursor_cell = null;
}
if (this.cursor.enabled) {
this.cursor_cell = this.cgrid[this.cursor.row-1][this.cursor.column-1];
this.cursor_cell.td.dataset.cursor = "";
}
}
private handle_ind_screen(screen: IndScreen) {
let rows = screen.rows || [];
for (let row_e of rows) {
let row_c = this.cgrid[row_e.row - 1];
for (let change of row_e.changes) {
let col_start = change.column - 1;
let count = ("text" in change) ? change.text.length : change.count;
let text = ("text" in change) ? change.text : null;
let new_gr: Set<GrElement> | null = null;
if (change.gr) {
new_gr = new Set();
new_gr.clear();
if (change.gr != "none") {
for (let gritem of change.gr.split(",")) {
new_gr.add(gritem as GrElement);
}
}
}
for (let i = 0; i < count; i++) {
let cell = row_c[col_start+i];
cell.fg = change.fg || cell.fg;
cell.bg = change.bg || cell.bg;
cell.gr = new_gr || cell.gr;
if (text) {
cell.char = text[i];
}
cell.update();
}
}
}
if (screen.cursor) {
this.cursor = screen.cursor;
this.move_cursor();
}
}
private handle_ind_erase(erase: IndErase) {
if ("fg" in erase) {
this.def_bg = erase.bg
this.def_fg = erase.fg
}
if ("logical_rows" in erase) {
this.resize_screen(erase.logical_rows, erase.logical_cols);
} else {
this.resize_screen(this.cgrid.length, this.cgrid[0].length)
}
}
}
let app = document.querySelector<HTMLDivElement>('#app')!;
// @ts-ignore
window.js3270 = new Js3270(app);

141
js3270/src/style.css Normal file
View File

@@ -0,0 +1,141 @@
$chroma: 100%;
$lightnessMain: 75%;
$lightnessIntense: 85%;
$lightnessDark: 60%;
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
/*line-height: 1.25;*/
font-synthesis: weight;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
/*box-sizing: content-box;*/
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
--chroma: 90%;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vanilla:hover {
filter: drop-shadow(0 0 2em #3178c6aa);
}
.card {
padding: 2em;
}
.read-the-docs {
color: #888;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}
.cgrid {
border-spacing: 0;
}
table.cgrid td {
white-space: pre;
font-family: "IBM P", "Operator Mono", monospace;
font-weight: 300;
padding: 0;
}
.cgrid [data-bg="neutralBlack"] {
background: oklch(0 0 0);
}
.cgrid [data-fg="neutralBlack"] { color: oklch(0.2 0 0); }
.cgrid [data-fg="blue"] { color: oklch($lightnessMain $chroma 240deg); }
.cgrid [data-fg="red"] { color: oklch($lightnessMain $chroma 20deg); }
.cgrid [data-fg="pink"] { color: oklch($lightnessMain $chroma 340deg); }
.cgrid [data-fg="green"] { color: oklch($lightnessMain $chroma 150deg); }
.cgrid [data-fg="turquoise"] { color: oklch($lightnessMain $chroma 190deg); }
.cgrid [data-fg="yellow"] { color: oklch($lightnessMain $chroma 110deg); }
.cgrid [data-fg="neutralWhite"] { color: oklch($lightnessMain 0 0); }
.cgrid [data-fg="black"] {color: #000; }
.cgrid [data-fg="deepBlue"] {color: oklch($lightnessDark $chroma 240deg); }
.cgrid [data-fg="orange"] {color: oklch($lightnessDark $chroma 70deg); }
.cgrid [data-fg="purple"] { color: oklch($lightnessDark $chroma 320deg);}
.cgrid [data-fg="paleGreen"] { color: oklch(92% $chroma 150deg); }
.cgrid [data-fg="paleTurquoise"] { color: oklch(95% $chroma 190deg); }
.cgrid [data-fg="gray"] { color: oklch(55% 0 0); }
.cgrid [data-fg="white"] { color: oklch($lightnessIntense 0 0); }
.cgrid [data-cursor] { box-shadow: inset 0px 0px 0 1px lime; }
.cgrid [data-gr~="underline"] { text-decoration: underline; }
.cgrid [data-gr~="highlight"] { font-synthesis: weight; font-weight: 400; }

251
js3270/src/suite3270.ts Normal file
View File

@@ -0,0 +1,251 @@
export type CodePage = {
name: string,
aliases?: string[],
}
export type ActionCause =
"command" | "default" | "file-transfer" | "httpd" | "idle" |
"keymap" | "macro" | "none" | "password" | "paste" | "peek" |
"screen-redraw" | "script" | "typeahead" | "ui"
export type ConnectionState =
"not-connected" | "reconnecting" | "resolving" |
"tcp-pending" | "tls-pending" | "telnet-pending" |
"connected-nvt" | "connected-nvt-charmode" |
"connected-3270" | "connected-unbound" |
"connected-e-nvt" | "connected-sscp" |
"connected-tn3270e"
export type IndConnection = {
state: ConnectionState,
host?: string,
cause?: ActionCause,
}
export type ComposeType = "std" | "ge"
export type Color =
"neutralBlack" | "blue" | "red" | "pink" | "green" | "turquoise" |
"yellow" | "neutralWhite" | "black" | "deepBlue" | "orange" | "purple" |
"paleGreen" | "paleTurquoise" | "gray" | "white"
export type IndErase = ({logical_rows: number, logical_cols: number} | {}) &
({fg: Color, bg: Color} | {})
export type IndHello = {version: string, build: string, copyright: string}
export type IndModel = {
model: number,
rows: number,
columns: number,
}
export type OiaCompose = { field: "compose"} &
(
{value: true, char: string, type: ComposeType} |
{value: false}
)
export type OiaInsert = {field: "insert", value: boolean}
export type OiaLock = { field: "lock", value?: string }
export type OiaLu = { field: "lu", value: string, lu?: string }
export type OiaNotUndera = { field: "not-undera", value: boolean }
export type OiaReverseInput = { field: "reverse-input", value: boolean }
export type OiaScreenTrace = { field: "screen-trace", value?: number }
export type OiaScript = { field: "script", value: boolean }
export type OiaTiming = { field: "timing", value?: string }
export type OiaTypeahead = { field: "typeahead", value: boolean }
export type IndOia =
OiaCompose | OiaInsert | OiaLock | OiaLu | OiaNotUndera | OiaReverseInput |
OiaScreenTrace | OiaScript | OiaTiming | OiaTypeahead
export type OiaFieldName = IndOia["field"]
export type IndProxy = {
name: string,
username: boolean,
port?: number,
}
export type IndSetting = {
name: string,
value?: any, // Todo: enhance this
cause?: ActionCause,
}
export type IndScreenMode = {
model: number,
rows: number,
columns: number,
color: boolean,
oversize: boolean,
extended: boolean,
}
export type IndTlsHello = {
supported: boolean,
provider: string,
options?: string[],
}
export type IndTls =
( { secure: true, verified: boolean } | { secure:false } ) &
{
session?: string,
"host-cert"?: string,
}
export type IndConnectAttempt = { "host-ip": string, port: string }
export type Cursor = {enabled: false} | {enabled:true, row: number, column: number }
export type IndFileTransfer = { cause: ActionCause } & (
{ state: "awaiting" } |
{ state: "running", bytes: number } |
{ state: "aborting" } |
{ state: "complete", text: string, success: boolean }
)
export type IndPassthru = {
"p-tag": string,
"parent-r-tag"?: string,
action: string,
args?: string[],
}
export type IndPopup = {
type: "connect-error" | "error" | "info" | "result" | "printer" | "child"
text: string,
// todo: refine
error?: string,
}
export type Change = {
column: number
// TODO: determine if this is a
gr?: string, // there's more structure than this, but can't represent in TS
fg?: Color,
bg?: Color,
} & ({count: number} | {text: string})
export type IndScreen = {
cursor?: Cursor,
rows?: {
row: number,
changes: Change[]
}[]
}
export type IndRunResult = {
"r-tag"?: string,
success: boolean,
text?: string[]
abort?: boolean
time: number
}
export type IndScroll = {
// TODO: refine
fg?: Color,
bg?: Color,
}
export type IndStats = {
"bytes-received": number,
"bytes-sent": number,
"records-received": number,
"records-sent": number,
}
export type IndTerminalName = {
text: string,
override: boolean,
}
export type IndThumb = {
top: number,
shown: number
saved: number
screen: number
back: number
}
export type IndTraceFile = {
name?: string
}
export type IndUiError = {
fatal: boolean
text: string
operation?: string
member?: string
line?: number
column?: number
}
// operations
export type OpRun = {
"r-tag"?: string,
type?: string,
// This is true of d3270, but b3270 offers more options
actions: Action[]
}
export type Action = {
action: string,
args?: string[],
}
export type OpRegister = {
name: string,
"help-text"?: string,
"help-params": string,
}
export type OpResult = {
"p-tag": string,
text?: string[]
}
export type Operation =
{run: OpRun} |
{register: OpRegister} |
{fail: OpResult} |
{succeed: OpResult}
export type Indication =
{bell: {}} |
{connection: IndConnection} |
{"connect-attempt": IndConnectAttempt} |
{erase: IndErase} |
{flipped: {value: boolean}} |
{font: {text: string}} |
{formatted: {state: boolean}} |
{ft: IndFileTransfer} |
{icon: {text: string}} |
{initialize: InitializeIndication[]} |
{oia: IndOia} |
{passthru: IndPassthru} |
{popup: IndPopup} |
{"run-result": IndRunResult} |
{screen: IndScreen} |
{"screen-mode": IndScreenMode} |
{scroll: IndScroll} |
{setting: IndSetting} |
{stats: IndStats} |
{thumb: IndThumb} |
{"trace-file": IndTraceFile} |
{tls: IndTls} |
{"ui-error": IndUiError} |
{"window-title": {text: string}}
export type InitializeIndication =
{"code-pages": CodePage[]} |
{connection: IndConnection} |
{erase: IndErase} |
{hello: IndHello} |
{models: IndModel} |
{oia: IndOia} |
{prefixes: {value: string}} |
{proxies: IndProxy[]} |
{"screen-mode": IndScreenMode} |
{setting: IndSetting} |
{"terminal-name": IndTerminalName} |
{thumb: IndThumb} |
{"tls-hello": IndTlsHello} |
{tls: IndTls} |
{"trace-file": IndTraceFile}

1
js3270/src/vite-env.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference types="vite/client" />

23
js3270/tsconfig.json Normal file
View File

@@ -0,0 +1,23 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
}

772
js3270/yarn.lock Normal file
View File

@@ -0,0 +1,772 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@csstools/cascade-layer-name-parser@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-1.0.2.tgz#35253f57c6c83d684fe396672486c644e6a84127"
integrity sha512-xm7Mgwej/wBfLoK0K5LfntmPJzoULayl1XZY9JYgQgT29JiqNw++sLnx95u5y9zCihblzkyaRYJrsRMhIBzRdg==
"@csstools/color-helpers@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@csstools/color-helpers/-/color-helpers-2.0.0.tgz#4ac578cb00b4e853b94f2250267d85ba957c4fc9"
integrity sha512-VcPjEnp07RNgz/D+oI2uIALg+IPCSl6mj0XhA3pl3F2bM2B95vgzatExmmzSg/X0zkh+R2v+jFY/J2pV/bnwpw==
"@csstools/css-calc@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@csstools/css-calc/-/css-calc-1.1.1.tgz#c622728b7f0c9aae70952623c2b0d3d114752987"
integrity sha512-Nh+iLCtjlooTzuR0lpmB8I6hPX/VupcGQ3Z1U2+wgJJ4fa8+cWkub+lCsbZcYPzBGsZLEL8fQAg+Na5dwEFJxg==
"@csstools/css-color-parser@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@csstools/css-color-parser/-/css-color-parser-1.1.2.tgz#e5956c0fe9c30d9f228b0e37173ff61f0dd89dad"
integrity sha512-MjW/VspbFSkvbuou7tUUu2+FAlAR7VJ/PA69M9EGKltThbONC8nyW33wHRzNvLzRLGstZLEO5X5oR7IMhMDi0A==
dependencies:
"@csstools/color-helpers" "^2.0.0"
"@csstools/css-calc" "^1.1.1"
"@csstools/css-parser-algorithms@^2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.1.1.tgz#7b62e6412a468a2d1096ed267edd1e4a7fd4a119"
integrity sha512-viRnRh02AgO4mwIQb2xQNJju0i+Fh9roNgmbR5xEuG7J3TGgxjnE95HnBLgsFJOJOksvcfxOUCgODcft6Y07cA==
"@csstools/css-tokenizer@^2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@csstools/css-tokenizer/-/css-tokenizer-2.1.1.tgz#07ae11a0a06365d7ec686549db7b729bc036528e"
integrity sha512-GbrTj2Z8MCTUv+52GE0RbFGM527xuXZ0Xa5g0Z+YN573uveS4G0qi6WNOMyz3yrFM/jaILTTwJ0+umx81EzqfA==
"@csstools/media-query-list-parser@^2.0.4":
version "2.0.4"
resolved "https://registry.yarnpkg.com/@csstools/media-query-list-parser/-/media-query-list-parser-2.0.4.tgz#466bd254041530dfd1e88bcb1921e8ca4af75b6a"
integrity sha512-GyYot6jHgcSDZZ+tLSnrzkR7aJhF2ZW6d+CXH66mjy5WpAQhZD4HDke2OQ36SivGRWlZJpAz7TzbW6OKlEpxAA==
"@csstools/postcss-cascade-layers@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-3.0.1.tgz#d839386e90428b448e3f75276bc01d516e852a0d"
integrity sha512-dD8W98dOYNOH/yX4V4HXOhfCOnvVAg8TtsL+qCGNoKXuq5z2C/d026wGWgySgC8cajXXo/wNezS31Glj5GcqrA==
dependencies:
"@csstools/selector-specificity" "^2.0.2"
postcss-selector-parser "^6.0.10"
"@csstools/postcss-color-function@^2.2.1":
version "2.2.1"
resolved "https://registry.yarnpkg.com/@csstools/postcss-color-function/-/postcss-color-function-2.2.1.tgz#fa28cc742c29ae63dbe0812dd9a03998a67dd318"
integrity sha512-T52iiqmzyKk09B9iNTQbuWa9Tn83SztXY7o6r2+j+o1BS/7+CiCjTgN2HgzybDmx8cr6XYhQ1BzqgV9tJzhrmw==
dependencies:
"@csstools/css-color-parser" "^1.1.2"
"@csstools/css-parser-algorithms" "^2.1.1"
"@csstools/css-tokenizer" "^2.1.1"
"@csstools/postcss-progressive-custom-properties" "^2.0.0"
"@csstools/postcss-color-mix-function@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-1.0.1.tgz#587f7df69d40f84c7bb4e9d7f178266cb7f6851b"
integrity sha512-NSVrzjVcI4TMzDfh6GKZXvEuelT81xpXzruuTNJrwKMTZXEBHY9G2gvmr0eC0wwmL8EF1TblXyPPfBbZobvfXg==
dependencies:
"@csstools/css-color-parser" "^1.1.2"
"@csstools/css-parser-algorithms" "^2.1.1"
"@csstools/css-tokenizer" "^2.1.1"
"@csstools/postcss-progressive-custom-properties" "^2.0.0"
"@csstools/postcss-font-format-keywords@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-2.0.2.tgz#d798d96f4af6cddcfee459f598c976e6011042d2"
integrity sha512-iKYZlIs6JsNT7NKyRjyIyezTCHLh4L4BBB3F5Nx7Dc4Z/QmBgX+YJFuUSar8IM6KclGiAUFGomXFdYxAwJydlA==
dependencies:
postcss-value-parser "^4.2.0"
"@csstools/postcss-gradients-interpolation-method@^3.0.4":
version "3.0.4"
resolved "https://registry.yarnpkg.com/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-3.0.4.tgz#c03402087c41feee0115f714cc87696e6424ba92"
integrity sha512-GgKoY7OlvL65UPigEdlrvMAUCR5kOQCjtue2/36TPrBNoRS6KM2KOqmjIVsxEwYYwK+L28pdnM8r10m03hhZxA==
dependencies:
"@csstools/css-color-parser" "^1.1.2"
"@csstools/css-parser-algorithms" "^2.1.1"
"@csstools/css-tokenizer" "^2.1.1"
"@csstools/postcss-progressive-custom-properties" "^2.0.0"
"@csstools/postcss-hwb-function@^2.2.1":
version "2.2.1"
resolved "https://registry.yarnpkg.com/@csstools/postcss-hwb-function/-/postcss-hwb-function-2.2.1.tgz#ab50918104e4ef500c42e55e4ccdd27fc33d52b9"
integrity sha512-eiqB4DIs+xqProAly7KwIgE04oze1YHb0QSCw/Y7062d9gpw+Cdif3Y0Z+Te+U7JROYdO0/0j91A6Qy8fo/Rlw==
dependencies:
"@csstools/css-color-parser" "^1.1.2"
"@csstools/css-parser-algorithms" "^2.1.1"
"@csstools/css-tokenizer" "^2.1.1"
"@csstools/postcss-ic-unit@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@csstools/postcss-ic-unit/-/postcss-ic-unit-2.0.2.tgz#5a5e481c53977deec3d63793788eec924d4c5f7d"
integrity sha512-N84qGTJkfLTPj2qOG5P4CIqGjpZBbjOEMKMn+UjO5wlb9lcBTfBsxCF0lQsFdWJUzBHYFOz19dL66v71WF3Pig==
dependencies:
"@csstools/postcss-progressive-custom-properties" "^2.0.0"
postcss-value-parser "^4.2.0"
"@csstools/postcss-is-pseudo-class@^3.2.0":
version "3.2.0"
resolved "https://registry.yarnpkg.com/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-3.2.0.tgz#1277cc187bdb075013341dab42b4140d1cafae27"
integrity sha512-uooelBL99jMg8ZD6xy0Pj1hSalchWmplcin00eI+JHpv1jW2iwbi1cn2UnVsToM4JLwJSZFzTSWCgSpmlyhe3A==
dependencies:
"@csstools/selector-specificity" "^2.0.0"
postcss-selector-parser "^6.0.10"
"@csstools/postcss-logical-float-and-clear@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@csstools/postcss-logical-float-and-clear/-/postcss-logical-float-and-clear-1.0.1.tgz#d255ea7aad18880930b63d8a04164f56182f2ecf"
integrity sha512-eO9z2sMLddvlfFEW5Fxbjyd03zaO7cJafDurK4rCqyRt9P7aaWwha0LcSzoROlcZrw1NBV2JAp2vMKfPMQO1xw==
"@csstools/postcss-logical-resize@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@csstools/postcss-logical-resize/-/postcss-logical-resize-1.0.1.tgz#826d3de929d7d786c32c2c118f78e813a1c2cdec"
integrity sha512-x1ge74eCSvpBkDDWppl+7FuD2dL68WP+wwP2qvdUcKY17vJksz+XoE1ZRV38uJgS6FNUwC0AxrPW5gy3MxsDHQ==
dependencies:
postcss-value-parser "^4.2.0"
"@csstools/postcss-logical-viewport-units@^1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@csstools/postcss-logical-viewport-units/-/postcss-logical-viewport-units-1.0.3.tgz#63e212954015ecdc493878601c3daa4da6ba6714"
integrity sha512-6zqcyRg9HSqIHIPMYdt6THWhRmE5/tyHKJQLysn2TeDf/ftq7Em9qwMTx98t2C/7UxIsYS8lOiHHxAVjWn2WUg==
dependencies:
"@csstools/css-tokenizer" "^2.1.1"
"@csstools/postcss-media-minmax@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@csstools/postcss-media-minmax/-/postcss-media-minmax-1.0.2.tgz#77efc4fdd96c7ff97f0d714c940187d25fd87619"
integrity sha512-DsEykSINZTqlBefi1uSQBym1Rj0NQOj92dLRd5jUQpSy8yBVaXXmkiUgBUbb+gQh8imAdqPpz2v4sAUnw8yXXA==
dependencies:
"@csstools/css-calc" "^1.1.1"
"@csstools/css-parser-algorithms" "^2.1.1"
"@csstools/css-tokenizer" "^2.1.1"
"@csstools/media-query-list-parser" "^2.0.4"
"@csstools/postcss-media-queries-aspect-ratio-number-values@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-1.0.2.tgz#23ca3c3decc79d9089c2028ded20a97a2c784eee"
integrity sha512-rOSR5p+5m0joXUoitYgCyMqNCu97yfLsLG3cnNaM8VeJRCWHGEu5hE9Gv0M7n9A4wo2pYF8QqaxkTlWbSJY9Fg==
dependencies:
"@csstools/css-parser-algorithms" "^2.1.1"
"@csstools/css-tokenizer" "^2.1.1"
"@csstools/media-query-list-parser" "^2.0.4"
"@csstools/postcss-nested-calc@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@csstools/postcss-nested-calc/-/postcss-nested-calc-2.0.2.tgz#a0857650ef88b1aa7b094c7ea8ea1378c35695e0"
integrity sha512-jbwrP8rN4e7LNaRcpx3xpMUjhtt34I9OV+zgbcsYAAk6k1+3kODXJBf95/JMYWhu9g1oif7r06QVUgfWsKxCFw==
dependencies:
postcss-value-parser "^4.2.0"
"@csstools/postcss-normalize-display-values@^2.0.1":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-2.0.1.tgz#35dc188c5b4713cf902959fe3c8ce613fcb7543e"
integrity sha512-TQT5g3JQ5gPXC239YuRK8jFceXF9d25ZvBkyjzBGGoW5st5sPXFVQS8OjYb9IJ/K3CdfK4528y483cgS2DJR/w==
dependencies:
postcss-value-parser "^4.2.0"
"@csstools/postcss-oklab-function@^2.2.1":
version "2.2.1"
resolved "https://registry.yarnpkg.com/@csstools/postcss-oklab-function/-/postcss-oklab-function-2.2.1.tgz#4f8f4d8d69e6e479e094b5d327c7b259352e8b81"
integrity sha512-g4wrVopp6xXr1KetUK4Lj36P+PFPwvUUtd2gaqo7X/0xgJHmMtKMPhD9p77H9bmIpPtkIYQ8b7+7cdmrWNEVAw==
dependencies:
"@csstools/css-color-parser" "^1.1.2"
"@csstools/css-parser-algorithms" "^2.1.1"
"@csstools/css-tokenizer" "^2.1.1"
"@csstools/postcss-progressive-custom-properties" "^2.0.0"
"@csstools/postcss-progressive-custom-properties@^2.0.0", "@csstools/postcss-progressive-custom-properties@^2.1.0":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-2.1.1.tgz#82df9314451db63bf7f4975a4d32f148e85db490"
integrity sha512-6p8eO5+j+9hn4h2Klr9dbmya0GIb9SRrnPaCxqR1muVlV1waAZq6YkmlApEwXrox9qxggSwGZD5TnLRIY9f7WA==
dependencies:
postcss-value-parser "^4.2.0"
"@csstools/postcss-scope-pseudo-class@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@csstools/postcss-scope-pseudo-class/-/postcss-scope-pseudo-class-2.0.2.tgz#6325e1e3b321093c59b008ec670bb772e17f06fe"
integrity sha512-6Pvo4uexUCXt+Hz5iUtemQAcIuCYnL+ePs1khFR6/xPgC92aQLJ0zGHonWoewiBE+I++4gXK3pr+R1rlOFHe5w==
dependencies:
postcss-selector-parser "^6.0.10"
"@csstools/postcss-stepped-value-functions@^2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-2.1.1.tgz#f31aa0e7bd0ce3e4a0450573e1e27ce5e602b100"
integrity sha512-YCvdF0GCZK35nhLgs7ippcxDlRVe5QsSht3+EghqTjnYnyl3BbWIN6fYQ1dKWYTJ+7Bgi41TgqQFfJDcp9Xy/w==
dependencies:
"@csstools/css-calc" "^1.1.1"
"@csstools/css-parser-algorithms" "^2.1.1"
"@csstools/css-tokenizer" "^2.1.1"
"@csstools/postcss-text-decoration-shorthand@^2.2.3":
version "2.2.3"
resolved "https://registry.yarnpkg.com/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-2.2.3.tgz#e634a488aa5ba252907deb787ad6cc24b8c2bb0a"
integrity sha512-PADJidg/tdhDk120aWlGuDxsp5ZTc9Nx7GhJ8t0qBCk5fOgLK6V3DsB9X6sOAhDokIihXKzjtUu15puac5McWw==
dependencies:
"@csstools/color-helpers" "^2.0.0"
postcss-value-parser "^4.2.0"
"@csstools/postcss-trigonometric-functions@^2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-2.1.1.tgz#871a2048b0f81495d6cd8858ffb1fb04231ca741"
integrity sha512-XcXmHEFfHXhvYz40FtDlA4Fp4NQln2bWTsCwthd2c+MCnYArUYU3YaMqzR5CrKP3pMoGYTBnp5fMqf1HxItNyw==
dependencies:
"@csstools/css-calc" "^1.1.1"
"@csstools/css-parser-algorithms" "^2.1.1"
"@csstools/css-tokenizer" "^2.1.1"
"@csstools/postcss-unset-value@^2.0.1":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@csstools/postcss-unset-value/-/postcss-unset-value-2.0.1.tgz#67091dd6cff556bff896c95053eb070cc6b21c25"
integrity sha512-oJ9Xl29/yU8U7/pnMJRqAZd4YXNCfGEdcP4ywREuqm/xMqcgDNDppYRoCGDt40aaZQIEKBS79LytUDN/DHf0Ew==
"@csstools/selector-specificity@^2.0.0", "@csstools/selector-specificity@^2.0.1", "@csstools/selector-specificity@^2.0.2":
version "2.2.0"
resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz#2cbcf822bf3764c9658c4d2e568bd0c0cb748016"
integrity sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==
"@esbuild/android-arm64@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.18.tgz#4aa8d8afcffb4458736ca9b32baa97d7cb5861ea"
integrity sha512-/iq0aK0eeHgSC3z55ucMAHO05OIqmQehiGay8eP5l/5l+iEr4EIbh4/MI8xD9qRFjqzgkc0JkX0LculNC9mXBw==
"@esbuild/android-arm@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.18.tgz#74a7e95af4ee212ebc9db9baa87c06a594f2a427"
integrity sha512-EmwL+vUBZJ7mhFCs5lA4ZimpUH3WMAoqvOIYhVQwdIgSpHC8ImHdsRyhHAVxpDYUSm0lWvd63z0XH1IlImS2Qw==
"@esbuild/android-x64@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.18.tgz#1dcd13f201997c9fe0b204189d3a0da4eb4eb9b6"
integrity sha512-x+0efYNBF3NPW2Xc5bFOSFW7tTXdAcpfEg2nXmxegm4mJuVeS+i109m/7HMiOQ6M12aVGGFlqJX3RhNdYM2lWg==
"@esbuild/darwin-arm64@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.18.tgz#444f3b961d4da7a89eb9bd35cfa4415141537c2a"
integrity sha512-6tY+djEAdF48M1ONWnQb1C+6LiXrKjmqjzPNPWXhu/GzOHTHX2nh8Mo2ZAmBFg0kIodHhciEgUBtcYCAIjGbjQ==
"@esbuild/darwin-x64@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.18.tgz#a6da308d0ac8a498c54d62e0b2bfb7119b22d315"
integrity sha512-Qq84ykvLvya3dO49wVC9FFCNUfSrQJLbxhoQk/TE1r6MjHo3sFF2tlJCwMjhkBVq3/ahUisj7+EpRSz0/+8+9A==
"@esbuild/freebsd-arm64@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.18.tgz#b83122bb468889399d0d63475d5aea8d6829c2c2"
integrity sha512-fw/ZfxfAzuHfaQeMDhbzxp9mc+mHn1Y94VDHFHjGvt2Uxl10mT4CDavHm+/L9KG441t1QdABqkVYwakMUeyLRA==
"@esbuild/freebsd-x64@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.18.tgz#af59e0e03fcf7f221b34d4c5ab14094862c9c864"
integrity sha512-FQFbRtTaEi8ZBi/A6kxOC0V0E9B/97vPdYjY9NdawyLd4Qk5VD5g2pbWN2VR1c0xhzcJm74HWpObPszWC+qTew==
"@esbuild/linux-arm64@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.18.tgz#8551d72ba540c5bce4bab274a81c14ed01eafdcf"
integrity sha512-R7pZvQZFOY2sxUG8P6A21eq6q+eBv7JPQYIybHVf1XkQYC+lT7nDBdC7wWKTrbvMXKRaGudp/dzZCwL/863mZQ==
"@esbuild/linux-arm@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.18.tgz#e09e76e526df4f665d4d2720d28ff87d15cdf639"
integrity sha512-jW+UCM40LzHcouIaqv3e/oRs0JM76JfhHjCavPxMUti7VAPh8CaGSlS7cmyrdpzSk7A+8f0hiedHqr/LMnfijg==
"@esbuild/linux-ia32@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.18.tgz#47878860ce4fe73a36fd8627f5647bcbbef38ba4"
integrity sha512-ygIMc3I7wxgXIxk6j3V00VlABIjq260i967Cp9BNAk5pOOpIXmd1RFQJQX9Io7KRsthDrQYrtcx7QCof4o3ZoQ==
"@esbuild/linux-loong64@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.18.tgz#3f8fbf5267556fc387d20b2e708ce115de5c967a"
integrity sha512-bvPG+MyFs5ZlwYclCG1D744oHk1Pv7j8psF5TfYx7otCVmcJsEXgFEhQkbhNW8otDHL1a2KDINW20cfCgnzgMQ==
"@esbuild/linux-mips64el@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.18.tgz#9d896d8f3c75f6c226cbeb840127462e37738226"
integrity sha512-oVqckATOAGuiUOa6wr8TXaVPSa+6IwVJrGidmNZS1cZVx0HqkTMkqFGD2HIx9H1RvOwFeWYdaYbdY6B89KUMxA==
"@esbuild/linux-ppc64@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.18.tgz#3d9deb60b2d32c9985bdc3e3be090d30b7472783"
integrity sha512-3dLlQO+b/LnQNxgH4l9rqa2/IwRJVN9u/bK63FhOPB4xqiRqlQAU0qDU3JJuf0BmaH0yytTBdoSBHrb2jqc5qQ==
"@esbuild/linux-riscv64@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.18.tgz#8a943cf13fd24ff7ed58aefb940ef178f93386bc"
integrity sha512-/x7leOyDPjZV3TcsdfrSI107zItVnsX1q2nho7hbbQoKnmoeUWjs+08rKKt4AUXju7+3aRZSsKrJtaRmsdL1xA==
"@esbuild/linux-s390x@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.18.tgz#66cb01f4a06423e5496facabdce4f7cae7cb80e5"
integrity sha512-cX0I8Q9xQkL/6F5zWdYmVf5JSQt+ZfZD2bJudZrWD+4mnUvoZ3TDDXtDX2mUaq6upMFv9FlfIh4Gfun0tbGzuw==
"@esbuild/linux-x64@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.18.tgz#23c26050c6c5d1359c7b774823adc32b3883b6c9"
integrity sha512-66RmRsPlYy4jFl0vG80GcNRdirx4nVWAzJmXkevgphP1qf4dsLQCpSKGM3DUQCojwU1hnepI63gNZdrr02wHUA==
"@esbuild/netbsd-x64@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.18.tgz#789a203d3115a52633ff6504f8cbf757f15e703b"
integrity sha512-95IRY7mI2yrkLlTLb1gpDxdC5WLC5mZDi+kA9dmM5XAGxCME0F8i4bYH4jZreaJ6lIZ0B8hTrweqG1fUyW7jbg==
"@esbuild/openbsd-x64@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.18.tgz#d7b998a30878f8da40617a10af423f56f12a5e90"
integrity sha512-WevVOgcng+8hSZ4Q3BKL3n1xTv5H6Nb53cBrtzzEjDbbnOmucEVcZeGCsCOi9bAOcDYEeBZbD2SJNBxlfP3qiA==
"@esbuild/sunos-x64@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.18.tgz#ecad0736aa7dae07901ba273db9ef3d3e93df31f"
integrity sha512-Rzf4QfQagnwhQXVBS3BYUlxmEbcV7MY+BH5vfDZekU5eYpcffHSyjU8T0xucKVuOcdCsMo+Ur5wmgQJH2GfNrg==
"@esbuild/win32-arm64@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.18.tgz#58dfc177da30acf956252d7c8ae9e54e424887c4"
integrity sha512-Kb3Ko/KKaWhjeAm2YoT/cNZaHaD1Yk/pa3FTsmqo9uFh1D1Rfco7BBLIPdDOozrObj2sahslFuAQGvWbgWldAg==
"@esbuild/win32-ia32@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.18.tgz#340f6163172b5272b5ae60ec12c312485f69232b"
integrity sha512-0/xUMIdkVHwkvxfbd5+lfG7mHOf2FRrxNbPiKWg9C4fFrB8H0guClmaM3BFiRUYrznVoyxTIyC/Ou2B7QQSwmw==
"@esbuild/win32-x64@0.17.18":
version "0.17.18"
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.18.tgz#3a8e57153905308db357fd02f57c180ee3a0a1fa"
integrity sha512-qU25Ma1I3NqTSHJUOKi9sAH1/Mzuvlke0ioMJRthLXKm7JiSKVwFghlGbDLOO2sARECGhja4xYfRAZNPAkooYg==
autoprefixer@^10.4.14:
version "10.4.14"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.14.tgz#e28d49902f8e759dd25b153264e862df2705f79d"
integrity sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==
dependencies:
browserslist "^4.21.5"
caniuse-lite "^1.0.30001464"
fraction.js "^4.2.0"
normalize-range "^0.1.2"
picocolors "^1.0.0"
postcss-value-parser "^4.2.0"
browserslist@^4.21.5:
version "4.21.5"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7"
integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==
dependencies:
caniuse-lite "^1.0.30001449"
electron-to-chromium "^1.4.284"
node-releases "^2.0.8"
update-browserslist-db "^1.0.10"
caniuse-lite@^1.0.30001449, caniuse-lite@^1.0.30001464:
version "1.0.30001486"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001486.tgz#56a08885228edf62cbe1ac8980f2b5dae159997e"
integrity sha512-uv7/gXuHi10Whlj0pp5q/tsK/32J2QSqVRKQhs2j8VsDCjgyruAh/eEXHF822VqO9yT6iZKw3nRwZRSPBE9OQg==
css-blank-pseudo@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-5.0.2.tgz#3df5cd950f64de960974da05e76954fd3d7442f9"
integrity sha512-aCU4AZ7uEcVSUzagTlA9pHciz7aWPKA/YzrEkpdSopJ2pvhIxiQ5sYeMz1/KByxlIo4XBdvMNJAVKMg/GRnhfw==
dependencies:
postcss-selector-parser "^6.0.10"
css-has-pseudo@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-5.0.2.tgz#8798118c705d858b7aeb9d839a39edd901c1cc83"
integrity sha512-q+U+4QdwwB7T9VEW/LyO6CFrLAeLqOykC5mDqJXc7aKZAhDbq7BvGT13VGJe+IwBfdN2o3Xdw2kJ5IxwV1Sc9Q==
dependencies:
"@csstools/selector-specificity" "^2.0.1"
postcss-selector-parser "^6.0.10"
postcss-value-parser "^4.2.0"
css-prefers-color-scheme@^8.0.2:
version "8.0.2"
resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-8.0.2.tgz#a0671f54eb19ed0d30b952574c0af11ec355fb6d"
integrity sha512-OvFghizHJ45x7nsJJUSYLyQNTzsCU8yWjxAc/nhPQg1pbs18LMoET8N3kOweFDPy0JV0OSXN2iqRFhPBHYOeMA==
cssdb@^7.5.3:
version "7.5.4"
resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-7.5.4.tgz#e34dafee5184d67634604e345e389ca79ac179ea"
integrity sha512-fGD+J6Jlq+aurfE1VDXlLS4Pt0VtNlu2+YgfGOdMxRyl/HQ9bDiHTwSck1Yz8A97Dt/82izSK6Bp/4nVqacOsg==
cssesc@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
electron-to-chromium@^1.4.284:
version "1.4.392"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.392.tgz#57ec91fa02393ab32e46df6925ef309642a44680"
integrity sha512-TXQOMW9tnhIms3jGy/lJctLjICOgyueZFJ1KUtm6DTQ+QpxX3p7ZBwB6syuZ9KBuT5S4XX7bgY1ECPgfxKUdOg==
esbuild@^0.17.5:
version "0.17.18"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.18.tgz#f4f8eb6d77384d68cd71c53eb6601c7efe05e746"
integrity sha512-z1lix43jBs6UKjcZVKOw2xx69ffE2aG0PygLL5qJ9OS/gy0Ewd1gW/PUQIOIQGXBHWNywSc0floSKoMFF8aK2w==
optionalDependencies:
"@esbuild/android-arm" "0.17.18"
"@esbuild/android-arm64" "0.17.18"
"@esbuild/android-x64" "0.17.18"
"@esbuild/darwin-arm64" "0.17.18"
"@esbuild/darwin-x64" "0.17.18"
"@esbuild/freebsd-arm64" "0.17.18"
"@esbuild/freebsd-x64" "0.17.18"
"@esbuild/linux-arm" "0.17.18"
"@esbuild/linux-arm64" "0.17.18"
"@esbuild/linux-ia32" "0.17.18"
"@esbuild/linux-loong64" "0.17.18"
"@esbuild/linux-mips64el" "0.17.18"
"@esbuild/linux-ppc64" "0.17.18"
"@esbuild/linux-riscv64" "0.17.18"
"@esbuild/linux-s390x" "0.17.18"
"@esbuild/linux-x64" "0.17.18"
"@esbuild/netbsd-x64" "0.17.18"
"@esbuild/openbsd-x64" "0.17.18"
"@esbuild/sunos-x64" "0.17.18"
"@esbuild/win32-arm64" "0.17.18"
"@esbuild/win32-ia32" "0.17.18"
"@esbuild/win32-x64" "0.17.18"
escalade@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
fraction.js@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950"
integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==
fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
nanoid@^3.3.6:
version "3.3.6"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
node-releases@^2.0.8:
version "2.0.10"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f"
integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==
normalize-range@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
picocolors@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
postcss-attribute-case-insensitive@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-6.0.2.tgz#e843091859323342e461878d201ee70278809e01"
integrity sha512-IRuCwwAAQbgaLhxQdQcIIK0dCVXg3XDUnzgKD8iwdiYdwU4rMWRWyl/W9/0nA4ihVpq5pyALiHB2veBJ0292pw==
dependencies:
postcss-selector-parser "^6.0.10"
postcss-clamp@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/postcss-clamp/-/postcss-clamp-4.1.0.tgz#7263e95abadd8c2ba1bd911b0b5a5c9c93e02363"
integrity sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==
dependencies:
postcss-value-parser "^4.2.0"
postcss-color-functional-notation@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-5.0.2.tgz#6d03c928aa3a13487703af86c301bdcd501e7430"
integrity sha512-M6ygxWOyd6eWf3sd1Lv8xi4SeF4iBPfJvkfMU4ITh8ExJc1qhbvh/U8Cv/uOvBgUVOMDdScvCdlg8+hREQzs7w==
dependencies:
postcss-value-parser "^4.2.0"
postcss-color-hex-alpha@^9.0.2:
version "9.0.2"
resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-9.0.2.tgz#6d3ed50342802469880981a1999515d003ff7d79"
integrity sha512-SfPjgr//VQ/DOCf80STIAsdAs7sbIbxATvVmd+Ec7JvR8onz9pjawhq3BJM3Pie40EE3TyB0P6hft16D33Nlyg==
dependencies:
postcss-value-parser "^4.2.0"
postcss-color-rebeccapurple@^8.0.2:
version "8.0.2"
resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-8.0.2.tgz#c0f2dcf1ef4dd393314920aa181cca8c390a2648"
integrity sha512-xWf/JmAxVoB5bltHpXk+uGRoGFwu4WDAR7210el+iyvTdqiKpDhtcT8N3edXMoVJY0WHFMrKMUieql/wRNiXkw==
dependencies:
postcss-value-parser "^4.2.0"
postcss-custom-media@^9.1.3:
version "9.1.3"
resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-9.1.3.tgz#68bb2ae377bb07c19f03f252930cc380af894dce"
integrity sha512-W1C4Fu6KAZ7sKYQCuGMr8gyaE4BtjTQGPLVS4m0WCaWM6l7PgVbvmDeb4ClBc5R/7kdwESYf0hdxGtEPhi9CLA==
dependencies:
"@csstools/cascade-layer-name-parser" "^1.0.2"
"@csstools/css-parser-algorithms" "^2.1.1"
"@csstools/css-tokenizer" "^2.1.1"
"@csstools/media-query-list-parser" "^2.0.4"
postcss-custom-properties@^13.1.5:
version "13.1.5"
resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-13.1.5.tgz#75567e3b4a664f820bcc3ba8b6ae3c8d27db05d1"
integrity sha512-98DXk81zTGqMVkGANysMHbGIg3voH383DYo3/+c+Abzay3nao+vM/f4Jgzsakk9S7BDsEw5DiW7sFy5G4W2wLA==
dependencies:
"@csstools/cascade-layer-name-parser" "^1.0.2"
"@csstools/css-parser-algorithms" "^2.1.1"
"@csstools/css-tokenizer" "^2.1.1"
postcss-value-parser "^4.2.0"
postcss-custom-selectors@^7.1.3:
version "7.1.3"
resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-7.1.3.tgz#047e2bc4726fe8e448c23047c99785fcdbe1ef87"
integrity sha512-GTVscax6O/8s7agFF0HsOoIyjrnAbLjgCUle8tn+0oDGJuVx7p56U7ClSRoC49poxFuMfu2B4Q8GnxSCOeuFKw==
dependencies:
"@csstools/cascade-layer-name-parser" "^1.0.2"
"@csstools/css-parser-algorithms" "^2.1.1"
"@csstools/css-tokenizer" "^2.1.1"
postcss-selector-parser "^6.0.4"
postcss-dir-pseudo-class@^7.0.2:
version "7.0.2"
resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-7.0.2.tgz#71618b7eb4abe067845d11b3c8f322760c9b3e88"
integrity sha512-cMnslilYxBf9k3qejnovrUONZx1rXeUZJw06fgIUBzABJe3D2LiLL5WAER7Imt3nrkaIgG05XZBztueLEf5P8w==
dependencies:
postcss-selector-parser "^6.0.10"
postcss-double-position-gradients@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-4.0.2.tgz#855a23201f26be447210504e9b668429cbf4640c"
integrity sha512-GXL1RmFREDK4Q9aYvI2RhVrA6a6qqSMQQ5ke8gSH1xgV6exsqbcJpIumC7AOgooH6/WIG3/K/T8xxAiVHy/tJg==
dependencies:
"@csstools/postcss-progressive-custom-properties" "^2.0.0"
postcss-value-parser "^4.2.0"
postcss-focus-visible@^8.0.2:
version "8.0.2"
resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-8.0.2.tgz#a7ac26ffe3e9c2bd17d7200d75e2d79ee8110891"
integrity sha512-f/Vd+EC/GaKElknU59esVcRYr/Y3t1ZAQyL4u2xSOgkDy4bMCmG7VP5cGvj3+BTLNE9ETfEuz2nnt4qkZwTTeA==
dependencies:
postcss-selector-parser "^6.0.10"
postcss-focus-within@^7.0.2:
version "7.0.2"
resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-7.0.2.tgz#5d2c866030e66ed22b204c9506de640943310b1c"
integrity sha512-AHAJ89UQBcqBvFgQJE9XasGuwMNkKsGj4D/f9Uk60jFmEBHpAL14DrnSk3Rj+SwZTr/WUG+mh+Rvf8fid/346w==
dependencies:
postcss-selector-parser "^6.0.10"
postcss-font-variant@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz#efd59b4b7ea8bb06127f2d031bfbb7f24d32fa66"
integrity sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==
postcss-gap-properties@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-4.0.1.tgz#0347d6a84a46bfbe88bedc542cc4b354e04a8338"
integrity sha512-V5OuQGw4lBumPlwHWk/PRfMKjaq/LTGR4WDTemIMCaMevArVfCCA9wBJiL1VjDAd+rzuCIlkRoRvDsSiAaZ4Fg==
postcss-image-set-function@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-5.0.2.tgz#088e0f535f43e74d6ea8033ff7b0482e2735ea6e"
integrity sha512-Sszjwo0ubETX0Fi5MvpYzsONwrsjeabjMoc5YqHvURFItXgIu3HdCjcVuVKGMPGzKRhgaknmdM5uVWInWPJmeg==
dependencies:
postcss-value-parser "^4.2.0"
postcss-initial@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-4.0.1.tgz#529f735f72c5724a0fb30527df6fb7ac54d7de42"
integrity sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==
postcss-lab-function@^5.2.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-5.2.1.tgz#a1f324fa5c098bddf36de221abcc32070c77b5db"
integrity sha512-u71Adr4nWi+4EmSZq5EV/fg9d1dYO6W26RNtT9LISEyjhH1q23vJIUkSqRwHgD6v7xxsxLOY5cSdVyaNE6rqzw==
dependencies:
"@csstools/css-color-parser" "^1.1.2"
"@csstools/css-parser-algorithms" "^2.1.1"
"@csstools/css-tokenizer" "^2.1.1"
"@csstools/postcss-progressive-custom-properties" "^2.0.0"
postcss-logical@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-6.1.0.tgz#c33ae75d3edaea7eb821e76dc4e6d0ecedc3200d"
integrity sha512-qb1+LpClhYjxac8SfOcWotnY3unKZesDqIOm+jnGt8rTl7xaIWpE2bPGZHxflOip1E/4ETo79qlJyRL3yrHn1g==
dependencies:
postcss-value-parser "^4.2.0"
postcss-nesting@^11.2.1:
version "11.2.2"
resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-11.2.2.tgz#ddedfea5a1fdcd8d753298d82297ad15d5640c0f"
integrity sha512-aOTiUniAB1bcPE6GGiynWRa6PZFPhOTAm5q3q5cem6QeSijIHHkWr6gs65ukCZMXeak8yXeZVbBJET3VM+HlhA==
dependencies:
"@csstools/selector-specificity" "^2.0.0"
postcss-selector-parser "^6.0.10"
postcss-opacity-percentage@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/postcss-opacity-percentage/-/postcss-opacity-percentage-2.0.0.tgz#c0a56060cd4586e3f954dbde1efffc2deed53002"
integrity sha512-lyDrCOtntq5Y1JZpBFzIWm2wG9kbEdujpNt4NLannF+J9c8CgFIzPa80YQfdza+Y+yFfzbYj/rfoOsYsooUWTQ==
postcss-overflow-shorthand@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-4.0.1.tgz#cb61ca24d8c4e1dbf14d85181b017cfa6953aa34"
integrity sha512-HQZ0qi/9iSYHW4w3ogNqVNr2J49DHJAl7r8O2p0Meip38jsdnRPgiDW7r/LlLrrMBMe3KHkvNtAV2UmRVxzLIg==
dependencies:
postcss-value-parser "^4.2.0"
postcss-page-break@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-3.0.4.tgz#7fbf741c233621622b68d435babfb70dd8c1ee5f"
integrity sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==
postcss-place@^8.0.1:
version "8.0.1"
resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-8.0.1.tgz#408d7a27e99192df51c95fe62a3a34def62aa66a"
integrity sha512-Ow2LedN8sL4pq8ubukO77phSVt4QyCm35ZGCYXKvRFayAwcpgB0sjNJglDoTuRdUL32q/ZC1VkPBo0AOEr4Uiw==
dependencies:
postcss-value-parser "^4.2.0"
postcss-preset-env@^8.3.2:
version "8.3.2"
resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-8.3.2.tgz#9ec368e0f0df9c693d52b69d525d366fe4b1833a"
integrity sha512-VSAOsfxTXzO/gX5QljC8x8hN3ABbD9iqqLgqHqohBdNI5FhJptwpl96kpu+kYvvzK7BWwaHYou0IeYrp+NqmcQ==
dependencies:
"@csstools/postcss-cascade-layers" "^3.0.1"
"@csstools/postcss-color-function" "^2.2.1"
"@csstools/postcss-color-mix-function" "^1.0.1"
"@csstools/postcss-font-format-keywords" "^2.0.2"
"@csstools/postcss-gradients-interpolation-method" "^3.0.4"
"@csstools/postcss-hwb-function" "^2.2.1"
"@csstools/postcss-ic-unit" "^2.0.2"
"@csstools/postcss-is-pseudo-class" "^3.2.0"
"@csstools/postcss-logical-float-and-clear" "^1.0.1"
"@csstools/postcss-logical-resize" "^1.0.1"
"@csstools/postcss-logical-viewport-units" "^1.0.3"
"@csstools/postcss-media-minmax" "^1.0.2"
"@csstools/postcss-media-queries-aspect-ratio-number-values" "^1.0.2"
"@csstools/postcss-nested-calc" "^2.0.2"
"@csstools/postcss-normalize-display-values" "^2.0.1"
"@csstools/postcss-oklab-function" "^2.2.1"
"@csstools/postcss-progressive-custom-properties" "^2.1.0"
"@csstools/postcss-scope-pseudo-class" "^2.0.2"
"@csstools/postcss-stepped-value-functions" "^2.1.1"
"@csstools/postcss-text-decoration-shorthand" "^2.2.3"
"@csstools/postcss-trigonometric-functions" "^2.1.1"
"@csstools/postcss-unset-value" "^2.0.1"
autoprefixer "^10.4.14"
browserslist "^4.21.5"
css-blank-pseudo "^5.0.2"
css-has-pseudo "^5.0.2"
css-prefers-color-scheme "^8.0.2"
cssdb "^7.5.3"
postcss-attribute-case-insensitive "^6.0.2"
postcss-clamp "^4.1.0"
postcss-color-functional-notation "^5.0.2"
postcss-color-hex-alpha "^9.0.2"
postcss-color-rebeccapurple "^8.0.2"
postcss-custom-media "^9.1.3"
postcss-custom-properties "^13.1.5"
postcss-custom-selectors "^7.1.3"
postcss-dir-pseudo-class "^7.0.2"
postcss-double-position-gradients "^4.0.2"
postcss-focus-visible "^8.0.2"
postcss-focus-within "^7.0.2"
postcss-font-variant "^5.0.0"
postcss-gap-properties "^4.0.1"
postcss-image-set-function "^5.0.2"
postcss-initial "^4.0.1"
postcss-lab-function "^5.2.1"
postcss-logical "^6.1.0"
postcss-nesting "^11.2.1"
postcss-opacity-percentage "^2.0.0"
postcss-overflow-shorthand "^4.0.1"
postcss-page-break "^3.0.4"
postcss-place "^8.0.1"
postcss-pseudo-class-any-link "^8.0.2"
postcss-replace-overflow-wrap "^4.0.0"
postcss-selector-not "^7.0.1"
postcss-value-parser "^4.2.0"
postcss-pseudo-class-any-link@^8.0.2:
version "8.0.2"
resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-8.0.2.tgz#f5738503f2045de0c4dc216eca99bd835f74e42e"
integrity sha512-FYTIuRE07jZ2CW8POvctRgArQJ43yxhr5vLmImdKUvjFCkR09kh8pIdlCwdx/jbFm7MiW4QP58L4oOUv3grQYA==
dependencies:
postcss-selector-parser "^6.0.10"
postcss-replace-overflow-wrap@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz#d2df6bed10b477bf9c52fab28c568b4b29ca4319"
integrity sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==
postcss-selector-not@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-7.0.1.tgz#8142e90c8eb6c8c5faecb3e9d96d4353d02e94fb"
integrity sha512-1zT5C27b/zeJhchN7fP0kBr16Cc61mu7Si9uWWLoA3Px/D9tIJPKchJCkUH3tPO5D0pCFmGeApAv8XpXBQJ8SQ==
dependencies:
postcss-selector-parser "^6.0.10"
postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.4:
version "6.0.12"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.12.tgz#2efae5ffab3c8bfb2b7fbf0c426e3bca616c4abb"
integrity sha512-NdxGCAZdRrwVI1sy59+Wzrh+pMMHxapGnpfenDVlMEXoOcvt4pGE0JLK9YY2F5dLxcFYA/YbVQKhcGU+FtSYQg==
dependencies:
cssesc "^3.0.0"
util-deprecate "^1.0.2"
postcss-simple-vars@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/postcss-simple-vars/-/postcss-simple-vars-7.0.1.tgz#836b3097a54dcd13dbd3c36a5dbdd512fad2954c"
integrity sha512-5GLLXaS8qmzHMOjVxqkk1TZPf1jMqesiI7qLhnlyERalG0sMbHIbJqrcnrpmZdKCLglHnRHoEBB61RtGTsj++A==
postcss-value-parser@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
postcss@^8.4.23:
version "8.4.23"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.23.tgz#df0aee9ac7c5e53e1075c24a3613496f9e6552ab"
integrity sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==
dependencies:
nanoid "^3.3.6"
picocolors "^1.0.0"
source-map-js "^1.0.2"
rollup@^3.21.0:
version "3.21.6"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.21.6.tgz#f5649ccdf8fcc7729254faa457cbea9547eb86db"
integrity sha512-SXIICxvxQxR3D4dp/3LDHZIJPC8a4anKMHd4E3Jiz2/JnY+2bEjqrOokAauc5ShGVNFHlEFjBXAXlaxkJqIqSg==
optionalDependencies:
fsevents "~2.3.2"
source-map-js@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
typescript@^5.0.2:
version "5.0.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b"
integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==
update-browserslist-db@^1.0.10:
version "1.0.11"
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940"
integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==
dependencies:
escalade "^3.1.1"
picocolors "^1.0.0"
util-deprecate@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
vite@^4.3.2:
version "4.3.5"
resolved "https://registry.yarnpkg.com/vite/-/vite-4.3.5.tgz#3871fe0f4b582ea7f49a85386ac80e84826367d9"
integrity sha512-0gEnL9wiRFxgz40o/i/eTBwm+NEbpUeTWhzKrZDSdKm6nplj+z4lKz8ANDgildxHm47Vg8EUia0aicKbawUVVA==
dependencies:
esbuild "^0.17.5"
postcss "^8.4.23"
rollup "^3.21.0"
optionalDependencies:
fsevents "~2.3.2"