electron-cli 0.3.0-alpha.2 → 0.3.0-alpha.4
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.lock +96 -1
- package/Cargo.toml +2 -1
- package/README.md +28 -9
- package/package.json +2 -1
- package/src/cli.rs +120 -3
- package/src/commands/init.rs +413 -27
- package/src/commands/make.rs +426 -0
- package/src/commands/mod.rs +3 -0
- package/src/commands/package.rs +703 -0
- package/src/commands/plan.rs +50 -5
- package/src/commands/start.rs +287 -0
- package/src/main.rs +3 -0
- package/templates/minimal/gitignore +5 -0
- package/templates/minimal/src/index.html +82 -0
- package/templates/minimal/src/main.js +33 -0
- package/templates/minimal/src/preload.js +6 -0
- package/templates/minimal/src/renderer.js +5 -0
package/src/commands/plan.rs
CHANGED
|
@@ -83,7 +83,9 @@ fn build_report(snapshot: &project::ProjectSnapshot) -> PlanReport {
|
|
|
83
83
|
let mut risks = Vec::new();
|
|
84
84
|
let mut notes = Vec::new();
|
|
85
85
|
|
|
86
|
-
if
|
|
86
|
+
if matches!(project_type, ProjectType::Electron) && snapshot.main.is_some() {
|
|
87
|
+
recommended_commands.insert("dev".to_string(), "electron-cli start".to_string());
|
|
88
|
+
} else if let Some(script) = first_script(snapshot, &["start", "dev"]) {
|
|
87
89
|
recommended_commands.insert("dev".to_string(), run_script(snapshot, script));
|
|
88
90
|
} else if snapshot.electron_dependency.is_some() && snapshot.main.is_some() {
|
|
89
91
|
recommended_commands.insert("dev".to_string(), package_exec(snapshot, "electron ."));
|
|
@@ -94,7 +96,9 @@ fn build_report(snapshot: &project::ProjectSnapshot) -> PlanReport {
|
|
|
94
96
|
missing.push("No start or dev script was found.".to_string());
|
|
95
97
|
}
|
|
96
98
|
|
|
97
|
-
if
|
|
99
|
+
if matches!(project_type, ProjectType::Electron) && snapshot.main.is_some() {
|
|
100
|
+
recommended_commands.insert("package".to_string(), "electron-cli package".to_string());
|
|
101
|
+
} else if let Some(script) = first_script(snapshot, &["package", "pack"]) {
|
|
98
102
|
recommended_commands.insert("package".to_string(), run_script(snapshot, script));
|
|
99
103
|
} else if matches!(project_type, ProjectType::ElectronForge) {
|
|
100
104
|
missing.push(
|
|
@@ -102,7 +106,9 @@ fn build_report(snapshot: &project::ProjectSnapshot) -> PlanReport {
|
|
|
102
106
|
);
|
|
103
107
|
}
|
|
104
108
|
|
|
105
|
-
if
|
|
109
|
+
if matches!(project_type, ProjectType::Electron) && snapshot.main.is_some() {
|
|
110
|
+
recommended_commands.insert("make".to_string(), "electron-cli make".to_string());
|
|
111
|
+
} else if let Some(script) = first_script(snapshot, &["make", "dist"]) {
|
|
106
112
|
recommended_commands.insert("make".to_string(), run_script(snapshot, script));
|
|
107
113
|
}
|
|
108
114
|
|
|
@@ -134,9 +140,9 @@ fn build_report(snapshot: &project::ProjectSnapshot) -> PlanReport {
|
|
|
134
140
|
}
|
|
135
141
|
|
|
136
142
|
if matches!(project_type, ProjectType::ElectronForge) {
|
|
137
|
-
notes.push("Electron Forge was detected;
|
|
143
|
+
notes.push("Electron Forge was detected; its scripts remain the safest path for Forge-managed apps today.".to_string());
|
|
138
144
|
} else if snapshot.electron_dependency.is_some() {
|
|
139
|
-
notes.push("Electron was detected without Forge;
|
|
145
|
+
notes.push("Electron was detected without Forge; electron-cli can start and package the current-platform app directly.".to_string());
|
|
140
146
|
} else {
|
|
141
147
|
notes.push("This does not currently look like an Electron app.".to_string());
|
|
142
148
|
}
|
|
@@ -232,4 +238,43 @@ mod tests {
|
|
|
232
238
|
);
|
|
233
239
|
assert!(report.risks.is_empty());
|
|
234
240
|
}
|
|
241
|
+
|
|
242
|
+
#[test]
|
|
243
|
+
fn plans_native_electron_cli_flow_for_plain_electron_app() {
|
|
244
|
+
let snapshot = project::ProjectSnapshot {
|
|
245
|
+
root: camino::Utf8PathBuf::from("/tmp/native-app"),
|
|
246
|
+
package_json: Some(camino::Utf8PathBuf::from("/tmp/native-app/package.json")),
|
|
247
|
+
name: Some("native-app".to_string()),
|
|
248
|
+
version: Some("0.1.0".to_string()),
|
|
249
|
+
main: Some("src/main.js".to_string()),
|
|
250
|
+
package_manager: Some("npm".to_string()),
|
|
251
|
+
scripts: BTreeMap::new(),
|
|
252
|
+
dependencies: BTreeMap::new(),
|
|
253
|
+
dev_dependencies: BTreeMap::from([("electron".to_string(), "30.0.0".to_string())]),
|
|
254
|
+
optional_dependencies: BTreeMap::new(),
|
|
255
|
+
peer_dependencies: BTreeMap::new(),
|
|
256
|
+
electron_dependency: Some("30.0.0".to_string()),
|
|
257
|
+
forge_dependencies: BTreeMap::new(),
|
|
258
|
+
signals: vec!["electron dependency declared".to_string()],
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
let report = build_report(&snapshot);
|
|
262
|
+
|
|
263
|
+
assert!(matches!(report.project_type, ProjectType::Electron));
|
|
264
|
+
assert_eq!(
|
|
265
|
+
report.recommended_commands.get("dev").map(String::as_str),
|
|
266
|
+
Some("electron-cli start")
|
|
267
|
+
);
|
|
268
|
+
assert_eq!(
|
|
269
|
+
report
|
|
270
|
+
.recommended_commands
|
|
271
|
+
.get("package")
|
|
272
|
+
.map(String::as_str),
|
|
273
|
+
Some("electron-cli package")
|
|
274
|
+
);
|
|
275
|
+
assert_eq!(
|
|
276
|
+
report.recommended_commands.get("make").map(String::as_str),
|
|
277
|
+
Some("electron-cli make")
|
|
278
|
+
);
|
|
279
|
+
}
|
|
235
280
|
}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
use std::{
|
|
2
|
+
path::{Path, PathBuf},
|
|
3
|
+
process::Command,
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
use anyhow::{bail, Context, Result};
|
|
7
|
+
use camino::Utf8PathBuf;
|
|
8
|
+
use serde::Serialize;
|
|
9
|
+
|
|
10
|
+
use crate::{cli::StartArgs, output, project::ProjectSnapshot};
|
|
11
|
+
|
|
12
|
+
#[derive(Debug, Serialize)]
|
|
13
|
+
struct StartReport {
|
|
14
|
+
project: ProjectSnapshot,
|
|
15
|
+
electron_path: Option<Utf8PathBuf>,
|
|
16
|
+
command: Vec<String>,
|
|
17
|
+
command_display: String,
|
|
18
|
+
passthrough_args: Vec<String>,
|
|
19
|
+
dry_run: bool,
|
|
20
|
+
status: StartStatus,
|
|
21
|
+
exit_code: Option<i32>,
|
|
22
|
+
warnings: Vec<String>,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
#[derive(Debug, Serialize)]
|
|
26
|
+
#[serde(rename_all = "kebab-case")]
|
|
27
|
+
enum StartStatus {
|
|
28
|
+
Planned,
|
|
29
|
+
Exited,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
pub fn run(args: StartArgs) -> Result<()> {
|
|
33
|
+
let snapshot = crate::project::inspect(&args.cwd)?;
|
|
34
|
+
let mut report = build_report(snapshot, &args)?;
|
|
35
|
+
|
|
36
|
+
if args.dry_run {
|
|
37
|
+
return print_report(&report, args.json);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let exit_code = execute_start(&report)?;
|
|
41
|
+
report.status = StartStatus::Exited;
|
|
42
|
+
report.exit_code = exit_code;
|
|
43
|
+
|
|
44
|
+
if args.json {
|
|
45
|
+
output::json(&report)?;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if let Some(code) = exit_code {
|
|
49
|
+
bail!("Electron exited with status code {code}");
|
|
50
|
+
} else {
|
|
51
|
+
Ok(())
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
fn build_report(snapshot: ProjectSnapshot, args: &StartArgs) -> Result<StartReport> {
|
|
56
|
+
let root = Path::new(snapshot.root.as_str());
|
|
57
|
+
let electron_path = find_electron_executable(root);
|
|
58
|
+
let mut warnings = Vec::new();
|
|
59
|
+
|
|
60
|
+
if snapshot.package_json.is_none() {
|
|
61
|
+
warnings.push("No package.json found.".to_string());
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if snapshot.electron_dependency.is_none() {
|
|
65
|
+
warnings.push("No electron dependency is declared in package.json.".to_string());
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if electron_path.is_none() {
|
|
69
|
+
warnings.push(
|
|
70
|
+
"Electron executable was not found under node_modules/electron/dist.".to_string(),
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let mut command = Vec::new();
|
|
75
|
+
if let Some(path) = &electron_path {
|
|
76
|
+
command.push(path_arg(path));
|
|
77
|
+
command.push(snapshot.root.to_string());
|
|
78
|
+
command.extend(args.electron_args.clone());
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let command_display = if command.is_empty() {
|
|
82
|
+
"electron executable not found".to_string()
|
|
83
|
+
} else {
|
|
84
|
+
display_command(&command)
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
Ok(StartReport {
|
|
88
|
+
project: snapshot,
|
|
89
|
+
electron_path: electron_path.map(utf8_path).transpose()?,
|
|
90
|
+
command,
|
|
91
|
+
command_display,
|
|
92
|
+
passthrough_args: args.electron_args.clone(),
|
|
93
|
+
dry_run: args.dry_run,
|
|
94
|
+
status: StartStatus::Planned,
|
|
95
|
+
exit_code: None,
|
|
96
|
+
warnings,
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
fn execute_start(report: &StartReport) -> Result<Option<i32>> {
|
|
101
|
+
if report.project.package_json.is_none() {
|
|
102
|
+
bail!("No package.json found. Run electron-cli start inside an Electron project.");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if report.project.electron_dependency.is_none() {
|
|
106
|
+
bail!("No electron dependency found. Install Electron before starting the app.");
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
let (program, args) = report
|
|
110
|
+
.command
|
|
111
|
+
.split_first()
|
|
112
|
+
.context("Electron executable was not found. Run your package manager install first.")?;
|
|
113
|
+
|
|
114
|
+
let status = Command::new(program)
|
|
115
|
+
.args(args)
|
|
116
|
+
.current_dir(report.project.root.as_str())
|
|
117
|
+
.status()
|
|
118
|
+
.with_context(|| format!("Could not execute {}", report.command_display))?;
|
|
119
|
+
|
|
120
|
+
if status.success() {
|
|
121
|
+
Ok(None)
|
|
122
|
+
} else {
|
|
123
|
+
Ok(status.code())
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
fn print_report(report: &StartReport, json: bool) -> Result<()> {
|
|
128
|
+
if json {
|
|
129
|
+
return output::json(report);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
println!("electron-cli start");
|
|
133
|
+
println!();
|
|
134
|
+
println!("Project");
|
|
135
|
+
println!(" root: {}", report.project.root);
|
|
136
|
+
match report.project.package_label() {
|
|
137
|
+
Some(label) => println!(" package: {label}"),
|
|
138
|
+
None => println!(" package: not found"),
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
println!();
|
|
142
|
+
println!("Command");
|
|
143
|
+
println!(" {}", report.command_display);
|
|
144
|
+
|
|
145
|
+
if !report.warnings.is_empty() {
|
|
146
|
+
println!();
|
|
147
|
+
println!("Warnings");
|
|
148
|
+
for warning in &report.warnings {
|
|
149
|
+
println!(" {warning}");
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
Ok(())
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
fn find_electron_executable(root: &Path) -> Option<PathBuf> {
|
|
157
|
+
let dist = root.join("node_modules/electron/dist");
|
|
158
|
+
let candidates = electron_executable_candidates(&dist);
|
|
159
|
+
|
|
160
|
+
candidates.into_iter().find(|path| path.exists())
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
fn electron_executable_candidates(dist: &Path) -> Vec<PathBuf> {
|
|
164
|
+
if cfg!(target_os = "macos") {
|
|
165
|
+
vec![
|
|
166
|
+
dist.join("Electron.app/Contents/MacOS/Electron"),
|
|
167
|
+
dist.join("electron"),
|
|
168
|
+
]
|
|
169
|
+
} else if cfg!(target_os = "windows") {
|
|
170
|
+
vec![dist.join("electron.exe")]
|
|
171
|
+
} else {
|
|
172
|
+
vec![dist.join("electron")]
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
fn display_command(command: &[String]) -> String {
|
|
177
|
+
command
|
|
178
|
+
.iter()
|
|
179
|
+
.map(|arg| shell_quote(arg))
|
|
180
|
+
.collect::<Vec<_>>()
|
|
181
|
+
.join(" ")
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
fn shell_quote(value: &str) -> String {
|
|
185
|
+
if value
|
|
186
|
+
.chars()
|
|
187
|
+
.all(|char| char.is_ascii_alphanumeric() || matches!(char, '.' | '/' | '-' | '_' | '@'))
|
|
188
|
+
{
|
|
189
|
+
value.to_string()
|
|
190
|
+
} else {
|
|
191
|
+
format!("'{}'", value.replace('\'', "'\\''"))
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
fn path_arg(path: &Path) -> String {
|
|
196
|
+
path.to_string_lossy().to_string()
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
fn utf8_path(path: PathBuf) -> Result<Utf8PathBuf> {
|
|
200
|
+
Utf8PathBuf::from_path_buf(path).map_err(|path| {
|
|
201
|
+
anyhow::anyhow!(
|
|
202
|
+
"Path contains invalid UTF-8 and cannot be represented in JSON: {}",
|
|
203
|
+
path.display()
|
|
204
|
+
)
|
|
205
|
+
})
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
#[cfg(test)]
|
|
209
|
+
mod tests {
|
|
210
|
+
use super::*;
|
|
211
|
+
use std::fs;
|
|
212
|
+
|
|
213
|
+
#[test]
|
|
214
|
+
fn plans_start_command_when_electron_dist_exists() {
|
|
215
|
+
let root = unique_temp_dir();
|
|
216
|
+
write_package_json(&root);
|
|
217
|
+
write_fake_electron(&root);
|
|
218
|
+
|
|
219
|
+
let args = StartArgs {
|
|
220
|
+
cwd: root.clone(),
|
|
221
|
+
dry_run: true,
|
|
222
|
+
json: true,
|
|
223
|
+
electron_args: vec!["--trace-warnings".to_string()],
|
|
224
|
+
};
|
|
225
|
+
let snapshot = crate::project::inspect(&root).expect("project should inspect");
|
|
226
|
+
let report = build_report(snapshot, &args).expect("report should build");
|
|
227
|
+
|
|
228
|
+
assert!(report.electron_path.is_some());
|
|
229
|
+
assert!(report.command_display.contains("--trace-warnings"));
|
|
230
|
+
assert!(report.warnings.is_empty());
|
|
231
|
+
|
|
232
|
+
let _ = fs::remove_dir_all(root);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
#[test]
|
|
236
|
+
fn reports_missing_electron_dist_as_warning() {
|
|
237
|
+
let root = unique_temp_dir();
|
|
238
|
+
write_package_json(&root);
|
|
239
|
+
|
|
240
|
+
let args = StartArgs {
|
|
241
|
+
cwd: root.clone(),
|
|
242
|
+
dry_run: true,
|
|
243
|
+
json: true,
|
|
244
|
+
electron_args: Vec::new(),
|
|
245
|
+
};
|
|
246
|
+
let snapshot = crate::project::inspect(&root).expect("project should inspect");
|
|
247
|
+
let report = build_report(snapshot, &args).expect("report should build");
|
|
248
|
+
|
|
249
|
+
assert!(report.electron_path.is_none());
|
|
250
|
+
assert!(report.warnings.contains(
|
|
251
|
+
&"Electron executable was not found under node_modules/electron/dist.".to_string()
|
|
252
|
+
));
|
|
253
|
+
|
|
254
|
+
let _ = fs::remove_dir_all(root);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
fn write_package_json(root: &Path) {
|
|
258
|
+
fs::write(
|
|
259
|
+
root.join("package.json"),
|
|
260
|
+
r#"{"name":"starter","version":"0.1.0","main":"src/main.js","devDependencies":{"electron":"30.0.0"}}"#,
|
|
261
|
+
)
|
|
262
|
+
.expect("package.json should be written");
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
fn write_fake_electron(root: &Path) {
|
|
266
|
+
let path = electron_executable_candidates(&root.join("node_modules/electron/dist"))
|
|
267
|
+
.into_iter()
|
|
268
|
+
.next()
|
|
269
|
+
.expect("candidate should exist");
|
|
270
|
+
fs::create_dir_all(path.parent().expect("candidate should have parent"))
|
|
271
|
+
.expect("electron parent should be created");
|
|
272
|
+
fs::write(path, "").expect("electron executable should be written");
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
fn unique_temp_dir() -> PathBuf {
|
|
276
|
+
let nanos = std::time::SystemTime::now()
|
|
277
|
+
.duration_since(std::time::UNIX_EPOCH)
|
|
278
|
+
.expect("clock should be after epoch")
|
|
279
|
+
.as_nanos();
|
|
280
|
+
let path = std::env::temp_dir().join(format!(
|
|
281
|
+
"electron-cli-start-test-{}-{nanos}",
|
|
282
|
+
std::process::id()
|
|
283
|
+
));
|
|
284
|
+
fs::create_dir_all(&path).expect("temp dir should be created");
|
|
285
|
+
path
|
|
286
|
+
}
|
|
287
|
+
}
|
package/src/main.rs
CHANGED
|
@@ -21,6 +21,9 @@ fn run() -> Result<()> {
|
|
|
21
21
|
Commands::Doctor(args) => commands::doctor::run(args),
|
|
22
22
|
Commands::Init(args) => commands::init::run(args),
|
|
23
23
|
Commands::Inspect(args) => commands::inspect::run(args),
|
|
24
|
+
Commands::Make(args) => commands::make::run(args),
|
|
25
|
+
Commands::Package(args) => commands::package::run(args),
|
|
24
26
|
Commands::Plan(args) => commands::plan::run(args),
|
|
27
|
+
Commands::Start(args) => commands::start::run(args),
|
|
25
28
|
}
|
|
26
29
|
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>electron-cli</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root {
|
|
9
|
+
color-scheme: light dark;
|
|
10
|
+
font-family:
|
|
11
|
+
Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
|
|
12
|
+
"Segoe UI", sans-serif;
|
|
13
|
+
background: #f5f5f2;
|
|
14
|
+
color: #1d2328;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
body {
|
|
18
|
+
margin: 0;
|
|
19
|
+
min-height: 100vh;
|
|
20
|
+
display: grid;
|
|
21
|
+
place-items: center;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
main {
|
|
25
|
+
width: min(720px, calc(100vw - 48px));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
h1 {
|
|
29
|
+
margin: 0 0 12px;
|
|
30
|
+
font-size: 5rem;
|
|
31
|
+
line-height: 0.92;
|
|
32
|
+
letter-spacing: 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
p {
|
|
36
|
+
max-width: 48rem;
|
|
37
|
+
margin: 0 0 24px;
|
|
38
|
+
font-size: 1.05rem;
|
|
39
|
+
line-height: 1.6;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
dl {
|
|
43
|
+
display: grid;
|
|
44
|
+
grid-template-columns: max-content 1fr;
|
|
45
|
+
gap: 8px 16px;
|
|
46
|
+
margin: 0;
|
|
47
|
+
padding-top: 20px;
|
|
48
|
+
border-top: 1px solid color-mix(in srgb, currentColor 24%, transparent);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
dt {
|
|
52
|
+
font-weight: 700;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
dd {
|
|
56
|
+
margin: 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@media (max-width: 640px) {
|
|
60
|
+
h1 {
|
|
61
|
+
font-size: 3rem;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
</style>
|
|
65
|
+
</head>
|
|
66
|
+
<body>
|
|
67
|
+
<main>
|
|
68
|
+
<h1>electron-cli</h1>
|
|
69
|
+
<p>
|
|
70
|
+
This app was generated by the experimental Rust-native electron-cli
|
|
71
|
+
template.
|
|
72
|
+
</p>
|
|
73
|
+
<dl>
|
|
74
|
+
<dt>Runtime</dt>
|
|
75
|
+
<dd id="runtime">Loading...</dd>
|
|
76
|
+
<dt>Platform</dt>
|
|
77
|
+
<dd id="platform">Loading...</dd>
|
|
78
|
+
</dl>
|
|
79
|
+
</main>
|
|
80
|
+
<script src="./renderer.js"></script>
|
|
81
|
+
</body>
|
|
82
|
+
</html>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const { app, BrowserWindow } = require("electron");
|
|
2
|
+
const path = require("node:path");
|
|
3
|
+
|
|
4
|
+
function createWindow() {
|
|
5
|
+
const window = new BrowserWindow({
|
|
6
|
+
width: 960,
|
|
7
|
+
height: 640,
|
|
8
|
+
minWidth: 640,
|
|
9
|
+
minHeight: 420,
|
|
10
|
+
title: "electron-cli",
|
|
11
|
+
webPreferences: {
|
|
12
|
+
preload: path.join(__dirname, "preload.js"),
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
window.loadFile(path.join(__dirname, "index.html"));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
app.whenReady().then(() => {
|
|
20
|
+
createWindow();
|
|
21
|
+
|
|
22
|
+
app.on("activate", () => {
|
|
23
|
+
if (BrowserWindow.getAllWindows().length === 0) {
|
|
24
|
+
createWindow();
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
app.on("window-all-closed", () => {
|
|
30
|
+
if (process.platform !== "darwin") {
|
|
31
|
+
app.quit();
|
|
32
|
+
}
|
|
33
|
+
});
|