elit 3.5.6 → 3.5.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.toml +1 -1
- package/README.md +1 -1
- package/desktop/build.rs +83 -0
- package/desktop/icon.rs +106 -0
- package/desktop/lib.rs +2 -0
- package/desktop/main.rs +235 -0
- package/desktop/native_main.rs +128 -0
- package/desktop/native_renderer/action_widgets.rs +184 -0
- package/desktop/native_renderer/app_models.rs +171 -0
- package/desktop/native_renderer/app_runtime.rs +140 -0
- package/desktop/native_renderer/container_rendering.rs +610 -0
- package/desktop/native_renderer/content_widgets.rs +634 -0
- package/desktop/native_renderer/css_models.rs +371 -0
- package/desktop/native_renderer/embedded_surfaces.rs +414 -0
- package/desktop/native_renderer/form_controls.rs +516 -0
- package/desktop/native_renderer/interaction_dispatch.rs +89 -0
- package/desktop/native_renderer/runtime_support.rs +135 -0
- package/desktop/native_renderer/utilities.rs +495 -0
- package/desktop/native_renderer/vector_drawing.rs +491 -0
- package/desktop/native_renderer.rs +4122 -0
- package/desktop/runtime/external.rs +422 -0
- package/desktop/runtime/mod.rs +67 -0
- package/desktop/runtime/quickjs.rs +106 -0
- package/desktop/window.rs +383 -0
- package/package.json +6 -3
- package/dist/build.d.mts +0 -20
- package/dist/chokidar.d.mts +0 -134
- package/dist/cli.d.mts +0 -81
- package/dist/config.d.mts +0 -254
- package/dist/coverage.d.mts +0 -85
- package/dist/database.d.mts +0 -52
- package/dist/desktop.d.mts +0 -68
- package/dist/dom.d.mts +0 -87
- package/dist/el.d.mts +0 -208
- package/dist/fs.d.mts +0 -255
- package/dist/hmr.d.mts +0 -38
- package/dist/http.d.mts +0 -169
- package/dist/https.d.mts +0 -108
- package/dist/index.d.mts +0 -13
- package/dist/mime-types.d.mts +0 -48
- package/dist/native.d.mts +0 -136
- package/dist/path.d.mts +0 -163
- package/dist/router.d.mts +0 -49
- package/dist/runtime.d.mts +0 -97
- package/dist/server-D0Dp4R5z.d.mts +0 -449
- package/dist/server.d.mts +0 -7
- package/dist/state.d.mts +0 -117
- package/dist/style.d.mts +0 -232
- package/dist/test-reporter.d.mts +0 -77
- package/dist/test-runtime.d.mts +0 -122
- package/dist/test.d.mts +0 -39
- package/dist/types.d.mts +0 -586
- package/dist/universal.d.mts +0 -21
- package/dist/ws.d.mts +0 -200
- package/dist/wss.d.mts +0 -108
- package/src/build.ts +0 -362
- package/src/chokidar.ts +0 -427
- package/src/cli.ts +0 -1162
- package/src/config.ts +0 -509
- package/src/coverage.ts +0 -1479
- package/src/database.ts +0 -1410
- package/src/desktop-auto-render.ts +0 -317
- package/src/desktop-cli.ts +0 -1533
- package/src/desktop.ts +0 -99
- package/src/dev-build.ts +0 -340
- package/src/dom.ts +0 -901
- package/src/el.ts +0 -183
- package/src/fs.ts +0 -609
- package/src/hmr.ts +0 -149
- package/src/http.ts +0 -856
- package/src/https.ts +0 -411
- package/src/index.ts +0 -16
- package/src/mime-types.ts +0 -222
- package/src/mobile-cli.ts +0 -2313
- package/src/native-background.ts +0 -444
- package/src/native-border.ts +0 -343
- package/src/native-canvas.ts +0 -260
- package/src/native-cli.ts +0 -414
- package/src/native-color.ts +0 -904
- package/src/native-estimation.ts +0 -194
- package/src/native-grid.ts +0 -590
- package/src/native-interaction.ts +0 -1289
- package/src/native-layout.ts +0 -568
- package/src/native-link.ts +0 -76
- package/src/native-render-support.ts +0 -361
- package/src/native-spacing.ts +0 -231
- package/src/native-state.ts +0 -318
- package/src/native-strings.ts +0 -46
- package/src/native-transform.ts +0 -120
- package/src/native-types.ts +0 -439
- package/src/native-typography.ts +0 -254
- package/src/native-units.ts +0 -441
- package/src/native-vector.ts +0 -910
- package/src/native.ts +0 -5606
- package/src/path.ts +0 -493
- package/src/pm-cli.ts +0 -2498
- package/src/preview-build.ts +0 -294
- package/src/render-context.ts +0 -138
- package/src/router.ts +0 -260
- package/src/runtime.ts +0 -97
- package/src/server.ts +0 -2294
- package/src/state.ts +0 -556
- package/src/style.ts +0 -1790
- package/src/test-globals.d.ts +0 -184
- package/src/test-reporter.ts +0 -609
- package/src/test-runtime.ts +0 -1359
- package/src/test.ts +0 -368
- package/src/types.ts +0 -381
- package/src/universal.ts +0 -81
- package/src/wapk-cli.ts +0 -3213
- package/src/workspace-package.ts +0 -102
- package/src/ws.ts +0 -648
- package/src/wss.ts +0 -241
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
use std::borrow::Cow;
|
|
2
|
+
use std::collections::HashMap;
|
|
3
|
+
use std::io::{Read, Write as IoWrite};
|
|
4
|
+
use std::net::TcpStream;
|
|
5
|
+
use std::panic::{self, AssertUnwindSafe};
|
|
6
|
+
use std::sync::{
|
|
7
|
+
Arc,
|
|
8
|
+
atomic::{AtomicBool, Ordering},
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
use tao::{
|
|
12
|
+
dpi::{LogicalPosition, LogicalSize, PhysicalPosition},
|
|
13
|
+
event::{Event, WindowEvent},
|
|
14
|
+
event_loop::{ControlFlow, EventLoopBuilder, EventLoopProxy, EventLoopWindowTarget},
|
|
15
|
+
window::{Icon, Window, WindowBuilder, WindowId},
|
|
16
|
+
};
|
|
17
|
+
#[cfg(target_os = "windows")]
|
|
18
|
+
use tao::platform::windows::WindowBuilderExtWindows;
|
|
19
|
+
use wry::WebViewBuilder;
|
|
20
|
+
|
|
21
|
+
use crate::icon::load_icon_bitmap;
|
|
22
|
+
use crate::runtime::{WindowCommand, WindowOptions};
|
|
23
|
+
|
|
24
|
+
// ── HTTP proxy (used by custom protocol) ─────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
/// Core HTTP proxy — works over any Read+Write stream (TCP socket or pipe).
|
|
27
|
+
fn do_proxy<S: Read + IoWrite>(
|
|
28
|
+
mut stream: S,
|
|
29
|
+
host: &str,
|
|
30
|
+
secret: Option<&str>,
|
|
31
|
+
req: &http::Request<Vec<u8>>,
|
|
32
|
+
) -> http::Response<Cow<'static, [u8]>> {
|
|
33
|
+
let method = req.method().as_str();
|
|
34
|
+
let pq = req.uri().path_and_query().map(|p| p.as_str()).unwrap_or("/");
|
|
35
|
+
let body = req.body();
|
|
36
|
+
|
|
37
|
+
let mut raw = format!(
|
|
38
|
+
"{} {} HTTP/1.1\r\nHost: {}\r\nConnection: close\r\n",
|
|
39
|
+
method, pq, host
|
|
40
|
+
);
|
|
41
|
+
for (k, v) in req.headers() {
|
|
42
|
+
let kl = k.as_str();
|
|
43
|
+
if !matches!(kl, "host" | "connection") {
|
|
44
|
+
if let Ok(vs) = v.to_str() {
|
|
45
|
+
raw.push_str(&format!("{}: {}\r\n", kl, vs));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if let Some(s) = secret {
|
|
50
|
+
raw.push_str(&format!("X-WAG-Internal: {}\r\n", s));
|
|
51
|
+
}
|
|
52
|
+
if !body.is_empty() {
|
|
53
|
+
raw.push_str(&format!("Content-Length: {}\r\n", body.len()));
|
|
54
|
+
}
|
|
55
|
+
raw.push_str("\r\n");
|
|
56
|
+
|
|
57
|
+
if stream.write_all(raw.as_bytes()).is_err() || stream.write_all(body).is_err() {
|
|
58
|
+
return err_response(502, "proxy: write failed");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
let mut bytes = Vec::new();
|
|
62
|
+
if stream.read_to_end(&mut bytes).is_err() {
|
|
63
|
+
return err_response(502, "proxy: read failed");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
parse_http_response(bytes)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/// Forward an `app://` request to `127.0.0.1:port` via TCP.
|
|
70
|
+
fn proxy_http(
|
|
71
|
+
port: u16,
|
|
72
|
+
secret: Option<&str>,
|
|
73
|
+
req: &http::Request<Vec<u8>>,
|
|
74
|
+
) -> http::Response<Cow<'static, [u8]>> {
|
|
75
|
+
let Ok(stream) = TcpStream::connect(format!("127.0.0.1:{}", port)) else {
|
|
76
|
+
return err_response(502, "proxy: connect failed");
|
|
77
|
+
};
|
|
78
|
+
stream.set_read_timeout(Some(std::time::Duration::from_secs(30))).ok();
|
|
79
|
+
do_proxy(stream, &format!("127.0.0.1:{}", port), secret, req)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/// Forward an `app://` request via named pipe (Windows) or Unix socket.
|
|
83
|
+
/// No TCP port exists — completely unreachable from any browser.
|
|
84
|
+
fn proxy_pipe_req(
|
|
85
|
+
path: &str,
|
|
86
|
+
secret: Option<&str>,
|
|
87
|
+
req: &http::Request<Vec<u8>>,
|
|
88
|
+
) -> http::Response<Cow<'static, [u8]>> {
|
|
89
|
+
#[cfg(target_os = "windows")]
|
|
90
|
+
{
|
|
91
|
+
let Ok(stream) = std::fs::OpenOptions::new().read(true).write(true).open(path) else {
|
|
92
|
+
return err_response(502, "proxy: pipe connect failed");
|
|
93
|
+
};
|
|
94
|
+
return do_proxy(stream, "localhost", secret, req);
|
|
95
|
+
}
|
|
96
|
+
#[cfg(not(target_os = "windows"))]
|
|
97
|
+
{
|
|
98
|
+
let Ok(stream) = std::os::unix::net::UnixStream::connect(path) else {
|
|
99
|
+
return err_response(502, "proxy: socket connect failed");
|
|
100
|
+
};
|
|
101
|
+
return do_proxy(stream, "localhost", secret, req);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
fn err_response(status: u16, msg: &'static str) -> http::Response<Cow<'static, [u8]>> {
|
|
106
|
+
http::Response::builder()
|
|
107
|
+
.status(status)
|
|
108
|
+
.body(Cow::Borrowed(msg.as_bytes()))
|
|
109
|
+
.unwrap()
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
fn parse_http_response(raw: Vec<u8>) -> http::Response<Cow<'static, [u8]>> {
|
|
113
|
+
let sep = raw.windows(4).position(|w| w == b"\r\n\r\n").unwrap_or(raw.len());
|
|
114
|
+
let hdr_src = std::str::from_utf8(&raw[..sep]).unwrap_or("");
|
|
115
|
+
let raw_body = raw.get(sep + 4..).unwrap_or_default();
|
|
116
|
+
|
|
117
|
+
let mut lines = hdr_src.lines();
|
|
118
|
+
let status: u16 = lines.next()
|
|
119
|
+
.and_then(|l| l.split_whitespace().nth(1))
|
|
120
|
+
.and_then(|s| s.parse().ok())
|
|
121
|
+
.unwrap_or(200);
|
|
122
|
+
|
|
123
|
+
let mut is_chunked = false;
|
|
124
|
+
let mut builder = http::Response::builder().status(status);
|
|
125
|
+
for line in lines {
|
|
126
|
+
if let Some((k, v)) = line.split_once(": ") {
|
|
127
|
+
let kl = k.to_lowercase();
|
|
128
|
+
if kl == "transfer-encoding" && v.to_lowercase().contains("chunked") {
|
|
129
|
+
is_chunked = true;
|
|
130
|
+
continue; // strip Transfer-Encoding from response to WebView
|
|
131
|
+
}
|
|
132
|
+
if matches!(kl.as_str(), "connection" | "keep-alive") { continue; }
|
|
133
|
+
builder = builder.header(k, v);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
let body = if is_chunked {
|
|
138
|
+
decode_chunked(raw_body)
|
|
139
|
+
} else {
|
|
140
|
+
raw_body.to_vec()
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
builder.body(Cow::Owned(body)).unwrap()
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/// Decode HTTP/1.1 chunked transfer encoding.
|
|
147
|
+
fn decode_chunked(data: &[u8]) -> Vec<u8> {
|
|
148
|
+
let mut out = Vec::new();
|
|
149
|
+
let mut pos = 0;
|
|
150
|
+
while pos < data.len() {
|
|
151
|
+
let nl = data[pos..].windows(2).position(|w| w == b"\r\n").map(|p| pos + p);
|
|
152
|
+
let Some(nl) = nl else { break };
|
|
153
|
+
let hex = std::str::from_utf8(&data[pos..nl]).unwrap_or("0");
|
|
154
|
+
let size = usize::from_str_radix(hex.split(';').next().unwrap_or("0").trim(), 16).unwrap_or(0);
|
|
155
|
+
if size == 0 { break; }
|
|
156
|
+
pos = nl + 2;
|
|
157
|
+
if pos + size > data.len() { break; }
|
|
158
|
+
out.extend_from_slice(&data[pos..pos + size]);
|
|
159
|
+
pos += size + 2; // skip trailing \r\n
|
|
160
|
+
}
|
|
161
|
+
out
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// ── Window / WebView builders ─────────────────────────────────────────────────
|
|
165
|
+
|
|
166
|
+
fn build_window(
|
|
167
|
+
opts: &WindowOptions,
|
|
168
|
+
target: &EventLoopWindowTarget<WindowCommand>,
|
|
169
|
+
) -> Window {
|
|
170
|
+
let title = opts.title.clone().unwrap_or_else(|| "elit".into());
|
|
171
|
+
let width = opts.width.unwrap_or(1024);
|
|
172
|
+
let height = opts.height.unwrap_or(768);
|
|
173
|
+
let resizable = opts.resizable.unwrap_or(true);
|
|
174
|
+
let transparent = opts.transparent.unwrap_or(false);
|
|
175
|
+
let decorations = opts.decorations.unwrap_or(true);
|
|
176
|
+
let always_on_top = opts.always_on_top.unwrap_or(false);
|
|
177
|
+
|
|
178
|
+
let icon = opts.icon.as_ref().and_then(|path| {
|
|
179
|
+
load_icon_bitmap(path.as_ref())
|
|
180
|
+
.ok()
|
|
181
|
+
.and_then(|bitmap| {
|
|
182
|
+
let (rgba, width, height) = bitmap.into_rgba();
|
|
183
|
+
Icon::from_rgba(rgba, width, height).ok()
|
|
184
|
+
})
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
let mut wb = WindowBuilder::new()
|
|
188
|
+
.with_title(&title)
|
|
189
|
+
.with_inner_size(LogicalSize::new(width, height))
|
|
190
|
+
.with_resizable(resizable)
|
|
191
|
+
.with_transparent(transparent)
|
|
192
|
+
.with_decorations(decorations)
|
|
193
|
+
.with_always_on_top(always_on_top);
|
|
194
|
+
|
|
195
|
+
if let (Some(x), Some(y)) = (opts.x, opts.y) {
|
|
196
|
+
wb = wb.with_position(LogicalPosition::new(x, y));
|
|
197
|
+
}
|
|
198
|
+
if opts.maximized.unwrap_or(false) { wb = wb.with_maximized(true); }
|
|
199
|
+
if let Some(false) = opts.minimizable { wb = wb.with_minimizable(false); }
|
|
200
|
+
if let Some(false) = opts.maximizable { wb = wb.with_maximizable(false); }
|
|
201
|
+
if let Some(false) = opts.closable { wb = wb.with_closable(false); }
|
|
202
|
+
|
|
203
|
+
#[cfg(target_os = "windows")]
|
|
204
|
+
if opts.skip_taskbar.unwrap_or(false) {
|
|
205
|
+
wb = wb.with_skip_taskbar(true);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if let Some(icon) = icon { wb = wb.with_window_icon(Some(icon)); }
|
|
209
|
+
|
|
210
|
+
let window = wb.build(target).expect("Failed to build window");
|
|
211
|
+
|
|
212
|
+
if opts.center.unwrap_or(false) {
|
|
213
|
+
if let Some(monitor) = window.current_monitor() {
|
|
214
|
+
let ms = monitor.size();
|
|
215
|
+
let ws = window.outer_size();
|
|
216
|
+
let x = (ms.width as i32 - ws.width as i32) / 2;
|
|
217
|
+
let y = (ms.height as i32 - ws.height as i32) / 2;
|
|
218
|
+
window.set_outer_position(PhysicalPosition::new(x.max(0), y.max(0)));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
window
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
fn build_webview(
|
|
226
|
+
opts: &WindowOptions,
|
|
227
|
+
window: &Window,
|
|
228
|
+
ipc_tx: std::sync::mpsc::Sender<String>,
|
|
229
|
+
proxy: EventLoopProxy<WindowCommand>,
|
|
230
|
+
) -> wry::WebView {
|
|
231
|
+
let mut builder = WebViewBuilder::new();
|
|
232
|
+
|
|
233
|
+
// ── Custom protocol proxy ─────────────────────────────────────────────────
|
|
234
|
+
// proxy_pipe → named pipe / Unix socket (no TCP port at all)
|
|
235
|
+
// proxy_port → TCP on 127.0.0.1 with secret-header guard
|
|
236
|
+
if let Some(pipe) = opts.proxy_pipe.clone() {
|
|
237
|
+
let secret: Option<String> = opts.proxy_secret.clone();
|
|
238
|
+
builder = builder.with_custom_protocol("app".into(), move |_wv_id, req| {
|
|
239
|
+
proxy_pipe_req(&pipe, secret.as_deref(), &req)
|
|
240
|
+
});
|
|
241
|
+
} else if let Some(port) = opts.proxy_port {
|
|
242
|
+
let secret: Option<String> = opts.proxy_secret.clone();
|
|
243
|
+
builder = builder.with_custom_protocol("app".into(), move |_wv_id, req| {
|
|
244
|
+
proxy_http(port, secret.as_deref(), &req)
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// ── Content ───────────────────────────────────────────────────────────────
|
|
249
|
+
builder = if opts.proxy_pipe.is_some() || opts.proxy_port.is_some() {
|
|
250
|
+
builder.with_url("app://localhost/")
|
|
251
|
+
} else if let Some(url) = &opts.url {
|
|
252
|
+
builder.with_url(url)
|
|
253
|
+
} else if let Some(html) = &opts.html {
|
|
254
|
+
builder.with_html(html)
|
|
255
|
+
} else {
|
|
256
|
+
builder.with_html(
|
|
257
|
+
r#"<!DOCTYPE html><html><head><meta charset="utf-8">
|
|
258
|
+
<style>body{margin:0;display:flex;align-items:center;justify-content:center;
|
|
259
|
+
height:100vh;font-family:sans-serif;background:#0f0f0f;color:#fff;}
|
|
260
|
+
h1{font-weight:300;letter-spacing:.2em;}</style></head>
|
|
261
|
+
<body><h1>elit</h1></body></html>"#,
|
|
262
|
+
)
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
if opts.devtools.unwrap_or(false) {
|
|
266
|
+
builder = builder.with_devtools(true);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// ── IPC ───────────────────────────────────────────────────────────────────
|
|
270
|
+
// "drag" is intercepted directly here to preserve mousedown timing.
|
|
271
|
+
builder = builder.with_ipc_handler(move |req| {
|
|
272
|
+
let body = req.body().to_string();
|
|
273
|
+
if body.contains("\"drag\"") {
|
|
274
|
+
if let Ok(v) = serde_json::from_str::<serde_json::Value>(&body) {
|
|
275
|
+
if v["cmd"].as_str() == Some("drag") {
|
|
276
|
+
proxy.send_event(WindowCommand::Drag).ok();
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
ipc_tx.send(body).ok();
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
builder.build(window).expect("Failed to build WebView")
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// ── Event loop ────────────────────────────────────────────────────────────────
|
|
288
|
+
|
|
289
|
+
pub fn run<F>(launch_runtime: F)
|
|
290
|
+
where
|
|
291
|
+
F: FnOnce(EventLoopProxy<WindowCommand>, std::sync::mpsc::Receiver<String>)
|
|
292
|
+
+ Send
|
|
293
|
+
+ 'static,
|
|
294
|
+
{
|
|
295
|
+
let event_loop = EventLoopBuilder::<WindowCommand>::with_user_event().build();
|
|
296
|
+
let proxy = event_loop.create_proxy();
|
|
297
|
+
let (ipc_tx, ipc_rx) = std::sync::mpsc::channel::<String>();
|
|
298
|
+
let has_window = Arc::new(AtomicBool::new(false));
|
|
299
|
+
let mut launch_runtime = Some(launch_runtime);
|
|
300
|
+
let mut ipc_rx = Some(ipc_rx);
|
|
301
|
+
let mut runtime_queued = false;
|
|
302
|
+
let mut runtime_started = false;
|
|
303
|
+
|
|
304
|
+
let mut store: HashMap<WindowId, (Window, wry::WebView)> = HashMap::new();
|
|
305
|
+
|
|
306
|
+
event_loop.run(move |event, target, control_flow| {
|
|
307
|
+
*control_flow = ControlFlow::Wait;
|
|
308
|
+
|
|
309
|
+
if !runtime_queued {
|
|
310
|
+
runtime_queued = true;
|
|
311
|
+
proxy.send_event(WindowCommand::StartRuntime).ok();
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
match event {
|
|
315
|
+
Event::UserEvent(WindowCommand::StartRuntime) => {
|
|
316
|
+
if runtime_started {
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
runtime_started = true;
|
|
321
|
+
let proxy_rt = proxy.clone();
|
|
322
|
+
let has_window_rt = has_window.clone();
|
|
323
|
+
let launch_runtime = launch_runtime.take().expect("runtime launcher missing");
|
|
324
|
+
let ipc_rx = ipc_rx.take().expect("ipc receiver missing");
|
|
325
|
+
|
|
326
|
+
std::thread::spawn(move || {
|
|
327
|
+
let result = panic::catch_unwind(AssertUnwindSafe(|| launch_runtime(proxy_rt.clone(), ipc_rx)));
|
|
328
|
+
if result.is_err() {
|
|
329
|
+
eprintln!("elit desktop runtime crashed before opening a window");
|
|
330
|
+
std::thread::sleep(std::time::Duration::from_millis(100));
|
|
331
|
+
if !has_window_rt.load(Ordering::SeqCst) {
|
|
332
|
+
proxy_rt.send_event(WindowCommand::Quit).ok();
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
Event::UserEvent(WindowCommand::Create(opts)) => {
|
|
338
|
+
has_window.store(true, Ordering::SeqCst);
|
|
339
|
+
let tx = ipc_tx.clone();
|
|
340
|
+
let px = proxy.clone();
|
|
341
|
+
let window = build_window(&opts, target);
|
|
342
|
+
let webview = build_webview(&opts, &window, tx, px);
|
|
343
|
+
store.insert(window.id(), (window, webview));
|
|
344
|
+
}
|
|
345
|
+
Event::UserEvent(WindowCommand::Eval(code)) => {
|
|
346
|
+
for (_, (_, wv)) in &store { wv.evaluate_script(&code).ok(); }
|
|
347
|
+
}
|
|
348
|
+
Event::UserEvent(WindowCommand::IpcMessage(_)) => {}
|
|
349
|
+
Event::UserEvent(WindowCommand::Minimize) => {
|
|
350
|
+
for (_, (w, _)) in &store { w.set_minimized(true); }
|
|
351
|
+
}
|
|
352
|
+
Event::UserEvent(WindowCommand::Maximize) => {
|
|
353
|
+
for (_, (w, _)) in &store { w.set_maximized(true); }
|
|
354
|
+
}
|
|
355
|
+
Event::UserEvent(WindowCommand::Unmaximize) => {
|
|
356
|
+
for (_, (w, _)) in &store { w.set_maximized(false); }
|
|
357
|
+
}
|
|
358
|
+
Event::UserEvent(WindowCommand::SetTitle(title)) => {
|
|
359
|
+
for (_, (w, _)) in &store { w.set_title(&title); }
|
|
360
|
+
}
|
|
361
|
+
Event::UserEvent(WindowCommand::Drag) => {
|
|
362
|
+
for (_, (w, _)) in &store { w.drag_window().ok(); }
|
|
363
|
+
}
|
|
364
|
+
Event::UserEvent(WindowCommand::SetPosition(x, y)) => {
|
|
365
|
+
for (_, (w, _)) in &store { w.set_outer_position(LogicalPosition::new(x, y)); }
|
|
366
|
+
}
|
|
367
|
+
Event::UserEvent(WindowCommand::SetSize(w, h)) => {
|
|
368
|
+
for (_, (win, _)) in &store { win.set_inner_size(LogicalSize::new(w, h)); }
|
|
369
|
+
}
|
|
370
|
+
Event::UserEvent(WindowCommand::SetAlwaysOnTop(v)) => {
|
|
371
|
+
for (_, (w, _)) in &store { w.set_always_on_top(v); }
|
|
372
|
+
}
|
|
373
|
+
Event::UserEvent(WindowCommand::Quit) => {
|
|
374
|
+
*control_flow = ControlFlow::Exit;
|
|
375
|
+
}
|
|
376
|
+
Event::WindowEvent { window_id, event: WindowEvent::CloseRequested, .. } => {
|
|
377
|
+
store.remove(&window_id);
|
|
378
|
+
if store.is_empty() { *control_flow = ControlFlow::Exit; }
|
|
379
|
+
}
|
|
380
|
+
_ => {}
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "elit",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.7",
|
|
4
4
|
"description": "Optimized lightweight library for creating DOM elements with reactive state",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -221,8 +221,11 @@
|
|
|
221
221
|
"typescript": "^5.3.0"
|
|
222
222
|
},
|
|
223
223
|
"files": [
|
|
224
|
-
"dist",
|
|
225
|
-
"
|
|
224
|
+
"dist/*.cjs",
|
|
225
|
+
"dist/*.mjs",
|
|
226
|
+
"dist/*.d.ts",
|
|
227
|
+
"dist/*.js",
|
|
228
|
+
"desktop",
|
|
226
229
|
"Cargo.toml",
|
|
227
230
|
"Cargo.lock",
|
|
228
231
|
"README.md",
|
package/dist/build.d.mts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { B as BuildOptions, a as BuildResult } from './server-D0Dp4R5z.mjs';
|
|
2
|
-
import './http.mjs';
|
|
3
|
-
import 'node:events';
|
|
4
|
-
import './ws.mjs';
|
|
5
|
-
import 'events';
|
|
6
|
-
import 'http';
|
|
7
|
-
import 'ws';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Build module for bundling applications
|
|
11
|
-
* Pure implementation with cross-runtime support
|
|
12
|
-
* Compatible with standard build tools API
|
|
13
|
-
* - Node.js: uses esbuild
|
|
14
|
-
* - Bun: uses Bun.build
|
|
15
|
-
* - Deno: uses Deno.emit
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
declare function build(options: BuildOptions): Promise<BuildResult>;
|
|
19
|
-
|
|
20
|
-
export { BuildOptions, BuildResult, build };
|
package/dist/chokidar.d.mts
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import { EventEmitter } from 'events';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* File watcher module with unified API across runtimes
|
|
5
|
-
* Pure implementation without external dependencies
|
|
6
|
-
* Compatible with 'chokidar' package API
|
|
7
|
-
* - Node.js: uses native fs.watch
|
|
8
|
-
* - Bun: uses native fs.watch with enhancements
|
|
9
|
-
* - Deno: uses Deno.watchFs
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Watch options
|
|
14
|
-
*/
|
|
15
|
-
interface WatchOptions {
|
|
16
|
-
/**
|
|
17
|
-
* Indicates whether the process should continue to run as long as files are being watched.
|
|
18
|
-
* If set to false, the process will continue running even if the watcher is closed.
|
|
19
|
-
*/
|
|
20
|
-
persistent?: boolean;
|
|
21
|
-
/**
|
|
22
|
-
* Indicates whether to watch files that don't have read permissions.
|
|
23
|
-
*/
|
|
24
|
-
ignorePermissionErrors?: boolean;
|
|
25
|
-
/**
|
|
26
|
-
* A function that takes one parameter (the path of the file/directory)
|
|
27
|
-
* and returns true to ignore or false to watch.
|
|
28
|
-
*/
|
|
29
|
-
ignored?: string | RegExp | ((path: string) => boolean);
|
|
30
|
-
/**
|
|
31
|
-
* If set to false, only the parent directory will be watched for new files.
|
|
32
|
-
*/
|
|
33
|
-
ignoreInitial?: boolean;
|
|
34
|
-
/**
|
|
35
|
-
* If set to true, symlinks will be followed.
|
|
36
|
-
*/
|
|
37
|
-
followSymlinks?: boolean;
|
|
38
|
-
/**
|
|
39
|
-
* Interval of file system polling (in milliseconds).
|
|
40
|
-
*/
|
|
41
|
-
interval?: number;
|
|
42
|
-
/**
|
|
43
|
-
* Interval of file system polling for binary files (in milliseconds).
|
|
44
|
-
*/
|
|
45
|
-
binaryInterval?: number;
|
|
46
|
-
/**
|
|
47
|
-
* If set to true, will provide fs.Stats object as second argument
|
|
48
|
-
* in add, addDir, and change events.
|
|
49
|
-
*/
|
|
50
|
-
alwaysStat?: boolean;
|
|
51
|
-
/**
|
|
52
|
-
* If set, limits how many levels of subdirectories will be traversed.
|
|
53
|
-
*/
|
|
54
|
-
depth?: number;
|
|
55
|
-
/**
|
|
56
|
-
* By default, add event fires when a file first appears on disk.
|
|
57
|
-
* Setting this will wait for the write to finish before firing.
|
|
58
|
-
*/
|
|
59
|
-
awaitWriteFinish?: boolean | {
|
|
60
|
-
stabilityThreshold?: number;
|
|
61
|
-
pollInterval?: number;
|
|
62
|
-
};
|
|
63
|
-
/**
|
|
64
|
-
* If set to true, will use fs.watchFile() (polling) instead of fs.watch().
|
|
65
|
-
*/
|
|
66
|
-
usePolling?: boolean;
|
|
67
|
-
/**
|
|
68
|
-
* Whether to use fsevents watching on macOS (if available).
|
|
69
|
-
*/
|
|
70
|
-
useFsEvents?: boolean;
|
|
71
|
-
/**
|
|
72
|
-
* The base path to watch.
|
|
73
|
-
*/
|
|
74
|
-
cwd?: string;
|
|
75
|
-
/**
|
|
76
|
-
* Whether to disable globbing.
|
|
77
|
-
*/
|
|
78
|
-
disableGlobbing?: boolean;
|
|
79
|
-
/**
|
|
80
|
-
* Automatically filter out artifacts that occur when using editors.
|
|
81
|
-
*/
|
|
82
|
-
atomic?: boolean | number;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* FSWatcher class - Compatible with chokidar
|
|
86
|
-
*/
|
|
87
|
-
declare class FSWatcher extends EventEmitter {
|
|
88
|
-
private _watcher;
|
|
89
|
-
private _closed;
|
|
90
|
-
private _watched;
|
|
91
|
-
constructor(options?: WatchOptions);
|
|
92
|
-
options: WatchOptions;
|
|
93
|
-
/**
|
|
94
|
-
* Add paths to be watched
|
|
95
|
-
*/
|
|
96
|
-
add(paths: string | string[]): FSWatcher;
|
|
97
|
-
/**
|
|
98
|
-
* Stop watching paths
|
|
99
|
-
*/
|
|
100
|
-
unwatch(paths: string | string[]): FSWatcher;
|
|
101
|
-
/**
|
|
102
|
-
* Close the watcher
|
|
103
|
-
*/
|
|
104
|
-
close(): Promise<void>;
|
|
105
|
-
/**
|
|
106
|
-
* Get watched paths
|
|
107
|
-
*/
|
|
108
|
-
getWatched(): {
|
|
109
|
-
[directory: string]: string[];
|
|
110
|
-
};
|
|
111
|
-
/**
|
|
112
|
-
* Internal method to set native watcher
|
|
113
|
-
* @internal
|
|
114
|
-
*/
|
|
115
|
-
_setWatcher(watcher: any): void;
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Watch files and directories
|
|
119
|
-
*/
|
|
120
|
-
declare function watch(paths: string | string[], options?: WatchOptions): FSWatcher;
|
|
121
|
-
/**
|
|
122
|
-
* Get current runtime
|
|
123
|
-
*/
|
|
124
|
-
declare function getRuntime(): 'node' | 'bun' | 'deno';
|
|
125
|
-
/**
|
|
126
|
-
* Default export
|
|
127
|
-
*/
|
|
128
|
-
declare const _default: {
|
|
129
|
-
watch: typeof watch;
|
|
130
|
-
FSWatcher: typeof FSWatcher;
|
|
131
|
-
getRuntime: typeof getRuntime;
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
export { FSWatcher, type WatchOptions, _default as default, getRuntime, watch };
|
package/dist/cli.d.mts
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
interface BuildOptions {
|
|
3
|
-
/** Entry file to build */
|
|
4
|
-
entry: string;
|
|
5
|
-
/** Output directory */
|
|
6
|
-
outDir?: string;
|
|
7
|
-
/** Output filename */
|
|
8
|
-
outFile?: string;
|
|
9
|
-
/** Enable minification */
|
|
10
|
-
minify?: boolean;
|
|
11
|
-
/** Generate sourcemap */
|
|
12
|
-
sourcemap?: boolean;
|
|
13
|
-
/** Target environment */
|
|
14
|
-
target?: 'es2015' | 'es2016' | 'es2017' | 'es2018' | 'es2019' | 'es2020' | 'es2021' | 'es2022' | 'esnext';
|
|
15
|
-
/** Output format */
|
|
16
|
-
format?: 'esm' | 'cjs' | 'iife';
|
|
17
|
-
/** Global name for IIFE format */
|
|
18
|
-
globalName?: string;
|
|
19
|
-
/** Target platform */
|
|
20
|
-
platform?: 'browser' | 'node' | 'neutral';
|
|
21
|
-
/** Base path for the application (injected into HTML) */
|
|
22
|
-
basePath?: string;
|
|
23
|
-
/** External dependencies (not bundled) */
|
|
24
|
-
external?: string[];
|
|
25
|
-
/** Module resolution options */
|
|
26
|
-
resolve?: {
|
|
27
|
-
/** Alias imports to other paths or modules */
|
|
28
|
-
alias?: Record<string, string>;
|
|
29
|
-
};
|
|
30
|
-
/** Enable tree shaking */
|
|
31
|
-
treeshake?: boolean;
|
|
32
|
-
/** Enable logging */
|
|
33
|
-
logging?: boolean;
|
|
34
|
-
/** Environment variables to inject (prefix with VITE_ for client access) */
|
|
35
|
-
env?: Record<string, string>;
|
|
36
|
-
/** Copy static files after build */
|
|
37
|
-
copy?: Array<{
|
|
38
|
-
from: string;
|
|
39
|
-
to: string;
|
|
40
|
-
transform?: (content: string, config: BuildOptions) => string;
|
|
41
|
-
}>;
|
|
42
|
-
/** Post-build hook */
|
|
43
|
-
onBuildEnd?: (result: BuildResult) => void | Promise<void>;
|
|
44
|
-
/** Emit a standalone preview server bundle after the client build */
|
|
45
|
-
standalonePreview?: boolean;
|
|
46
|
-
/** Emit a standalone development server bundle after the client build */
|
|
47
|
-
standaloneDev?: boolean;
|
|
48
|
-
/** Output filename for the standalone development server bundle (default: index.js) */
|
|
49
|
-
standaloneDevOutFile?: string;
|
|
50
|
-
/** Output filename for the standalone preview server bundle (default: index.js) */
|
|
51
|
-
standalonePreviewOutFile?: string;
|
|
52
|
-
}
|
|
53
|
-
interface BuildResult {
|
|
54
|
-
/** Output file path */
|
|
55
|
-
outputPath: string;
|
|
56
|
-
/** Build time in milliseconds */
|
|
57
|
-
buildTime: number;
|
|
58
|
-
/** Output file size in bytes */
|
|
59
|
-
size: number;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Main CLI for Elit
|
|
64
|
-
*/
|
|
65
|
-
|
|
66
|
-
declare function runDev(args: string[]): Promise<void>;
|
|
67
|
-
declare function runBuild(args: string[]): Promise<void>;
|
|
68
|
-
declare function runBuildDev(args: string[]): Promise<void>;
|
|
69
|
-
declare function runBuildPreview(args: string[]): Promise<void>;
|
|
70
|
-
declare function runPreview(args: string[]): Promise<void>;
|
|
71
|
-
declare function runTest(args: string[]): Promise<void>;
|
|
72
|
-
declare function runDesktop(args: string[]): Promise<void>;
|
|
73
|
-
declare function runMobile(args: string[]): Promise<void>;
|
|
74
|
-
declare function runNative(args: string[]): Promise<void>;
|
|
75
|
-
declare function runWapk(args: string[]): Promise<void>;
|
|
76
|
-
declare function runPm(args: string[]): Promise<void>;
|
|
77
|
-
declare function parseBuildArgs(args: string[]): Partial<BuildOptions>;
|
|
78
|
-
declare function parseBuildDevArgs(args: string[]): Partial<BuildOptions>;
|
|
79
|
-
declare function parseBuildPreviewArgs(args: string[]): Partial<BuildOptions>;
|
|
80
|
-
|
|
81
|
-
export { parseBuildArgs, parseBuildDevArgs, parseBuildPreviewArgs, runBuild, runBuildDev, runBuildPreview, runDesktop, runDev, runMobile, runNative, runPm, runPreview, runTest, runWapk };
|