Merge pull request #156 from Demonthos/create-dioxus-app

Make Dioxus create interactive
This commit is contained in:
Jon Kelley authored and GitHub committed 2023-06-28 16:56:38 -07:00
commit 737910f8ae
7 files changed
+1381 -516

No files matched your search

Generated
+1311 -443
View File
File diff suppressed because it is too large. Load diff
+8 -6
View File
@@ -11,7 +11,7 @@ license = "MIT/Apache-2.0"
[dependencies] [dependencies]
# cli core # cli core
clap = { version = "3.0.14", features = ["derive"] } clap = { version = "4.2", features = ["derive"] }
thiserror = "1.0.30" thiserror = "1.0.30"
wasm-bindgen-cli-support = "0.2" wasm-bindgen-cli-support = "0.2"
colored = "2.0.0" colored = "2.0.0"
@@ -77,12 +77,14 @@ ctrlc = "3.2.3"
# dioxus-rsx = "0.0.1" # dioxus-rsx = "0.0.1"
gitignore = "1.0.7" gitignore = "1.0.7"
dioxus-rsx = { version = "0.0.3" } dioxus-rsx = { git = "https://github.com/DioxusLabs/dioxus" }
dioxus-html = { version = "0.3", features = ["hot-reload-context"] } dioxus-html = { git = "https://github.com/DioxusLabs/dioxus", features = ["hot-reload-context"] }
dioxus-core = { version = "0.3", features = ["serialize"] } dioxus-core = { git = "https://github.com/DioxusLabs/dioxus", features = ["serialize"] }
dioxus-autofmt = "0.3.0" dioxus-autofmt = { git = "https://github.com/DioxusLabs/dioxus" }
rsx-rosetta = { version = "0.3" } rsx-rosetta = { git = "https://github.com/DioxusLabs/dioxus" }
open = "4.1.0" open = "4.1.0"
cargo-generate = "0.18.3"
toml_edit = "0.19.11"
[[bin]] [[bin]]
path = "src/main.rs" path = "src/main.rs"
+2 -2
View File
@@ -4,7 +4,7 @@ use super::*;
#[derive(Clone, Debug, Default, Deserialize, Parser)] #[derive(Clone, Debug, Default, Deserialize, Parser)]
pub struct ConfigOptsBuild { pub struct ConfigOptsBuild {
/// The index HTML file to drive the bundling process [default: index.html] /// The index HTML file to drive the bundling process [default: index.html]
#[clap(parse(from_os_str))] #[arg(long)]
pub target: Option<PathBuf>, pub target: Option<PathBuf>,
/// Build in release mode [default: false] /// Build in release mode [default: false]
@@ -37,7 +37,7 @@ pub struct ConfigOptsBuild {
#[derive(Clone, Debug, Default, Deserialize, Parser)] #[derive(Clone, Debug, Default, Deserialize, Parser)]
pub struct ConfigOptsServe { pub struct ConfigOptsServe {
/// The index HTML file to drive the bundling process [default: index.html] /// The index HTML file to drive the bundling process [default: index.html]
#[clap(parse(from_os_str))] #[arg(short, long)]
pub target: Option<PathBuf>, pub target: Option<PathBuf>,
/// Port of dev server /// Port of dev server
+49 -57
View File
@@ -1,14 +1,9 @@
use super::*; use super::*;
use crate::custom_error; use cargo_generate::{GenerateArgs, TemplatePath};
/// Build the Rust WASM app and all of its assets.
#[derive(Clone, Debug, Default, Deserialize, Parser)] #[derive(Clone, Debug, Default, Deserialize, Parser)]
#[clap(name = "create")] #[clap(name = "create")]
pub struct Create { pub struct Create {
/// Init project name
#[clap(default_value = ".")]
name: String,
/// Template path /// Template path
#[clap(default_value = "gh:dioxuslabs/dioxus-template", long)] #[clap(default_value = "gh:dioxuslabs/dioxus-template", long)]
template: String, template: String,
@@ -16,69 +11,66 @@ pub struct Create {
impl Create { impl Create {
pub fn create(self) -> Result<()> { pub fn create(self) -> Result<()> {
if Self::name_valid_check(self.name.clone()) { let mut args = GenerateArgs::default();
return custom_error!("❗Unsupported project name: '{}'.", &self.name); args.template_path = TemplatePath {
} auto_path: Some(self.template),
..Default::default()
};
let project_path = PathBuf::from(&self.name); let path = cargo_generate::generate(args)?;
if project_path.join("Dioxus.toml").is_file() || project_path.join("Cargo.toml").is_file() {
return custom_error!("🧨 Folder '{}' is initialized.", &self.name);
}
log::info!("🔧 Start: Creating new project '{}'.", self.name);
let output = Command::new("cargo")
.arg("generate")
.arg("--help")
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output()?;
// first run cargo fmt
let mut cmd = Command::new("cargo");
let cmd = cmd.arg("fmt").current_dir(&path);
let output = cmd.output().expect("failed to execute process");
if !output.status.success() { if !output.status.success() {
log::warn!("Tool is not installed: cargo-generate, try to install it."); log::error!("cargo fmt failed");
let install_output = Command::new("cargo") log::error!("stdout: {}", String::from_utf8_lossy(&output.stdout));
.arg("install") log::error!("stderr: {}", String::from_utf8_lossy(&output.stderr));
.arg("cargo-generate")
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.output()?;
if !install_output.status.success() {
return custom_error!("Try to install cargo-generate failed.");
}
} }
let generate_output = Command::new("cargo") // then format the toml
.arg("generate") let toml_paths = [path.join("Cargo.toml"), path.join("Dioxus.toml")];
.arg(&self.template) for toml_path in &toml_paths {
.arg("--name") let toml = std::fs::read_to_string(toml_path)?;
.arg(&self.name) let mut toml = toml.parse::<toml_edit::Document>().map_err(|e| {
.arg("--force") anyhow::anyhow!(
.stdout(Stdio::piped()) "failed to parse toml at {}: {}",
.stderr(Stdio::inherit()) toml_path.display(),
.output()?; e.to_string()
)
})?;
if !generate_output.status.success() { toml.as_table_mut().fmt();
return custom_error!("Generate project failed. Try to update cargo-generate.");
let as_string = toml.to_string();
let new_string = remove_tripple_newlines(&as_string);
let mut file = std::fs::File::create(toml_path)?;
file.write_all(new_string.as_bytes())?;
} }
let mut dioxus_file = File::open(project_path.join("Dioxus.toml"))?; // remove any tripple newlines from the readme
let mut meta_file = String::new(); let readme_path = path.join("README.md");
dioxus_file.read_to_string(&mut meta_file)?; let readme = std::fs::read_to_string(&readme_path)?;
meta_file = meta_file.replace("{{project-name}}", &self.name); let new_readme = remove_tripple_newlines(&readme);
meta_file = meta_file.replace("{{default-platform}}", "web"); let mut file = std::fs::File::create(readme_path)?;
File::create(project_path.join("Dioxus.toml"))?.write_all(meta_file.as_bytes())?; file.write_all(new_readme.as_bytes())?;
println!(); log::info!("Generated project at {}", path.display());
log::info!("💡 Project initialized:");
log::info!("🎯> cd ./{}", self.name);
log::info!("🎯> dioxus serve");
Ok(()) Ok(())
} }
}
fn name_valid_check(name: String) -> bool { fn remove_tripple_newlines(string: &str) -> String {
let r = Regex::new(r"^[a-zA-Z][a-zA-Z0-9\-_]$").unwrap(); let mut new_string = String::new();
r.is_match(&name) for char in string.chars() {
if char == '\n' {
if new_string.ends_with("\n\n") {
continue;
}
}
new_string.push(char);
} }
new_string
} }
-1
View File
@@ -17,7 +17,6 @@ use crate::{
}; };
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use html_parser::Dom; use html_parser::Dom;
use regex::Regex;
use serde::Deserialize; use serde::Deserialize;
use std::{ use std::{
fs::{remove_dir_all, File}, fs::{remove_dir_all, File},
+1 -1
View File
@@ -22,7 +22,7 @@ pub struct Translate {
pub raw: Option<String>, pub raw: Option<String>,
/// Output file, stdout if not present /// Output file, stdout if not present
#[clap(parse(from_os_str))] #[arg(short, long)]
pub output: Option<PathBuf>, pub output: Option<PathBuf>,
} }
+10 -6
View File
@@ -150,10 +150,11 @@ pub async fn startup_hot_reload(
let dist_path = config.out_dir.clone(); let dist_path = config.out_dir.clone();
let (reload_tx, _) = broadcast::channel(100); let (reload_tx, _) = broadcast::channel(100);
let map = FileMap::<HtmlCtx>::new(config.crate_dir.clone()); let FileMapBuildResult { map, errors } =
// for err in errors { FileMap::<HtmlCtx>::create(config.crate_dir.clone()).unwrap();
// log::error!("{}", err); for err in errors {
// } log::error!("{}", err);
}
let file_map = Arc::new(Mutex::new(map)); let file_map = Arc::new(Mutex::new(map));
let build_manager = Arc::new(BuildManager { let build_manager = Arc::new(BuildManager {
config: config.clone(), config: config.clone(),
@@ -219,10 +220,10 @@ pub async fn startup_hot_reload(
let mut map = file_map.lock().unwrap(); let mut map = file_map.lock().unwrap();
match map.update_rsx(&path, &crate_dir) { match map.update_rsx(&path, &crate_dir) {
UpdateResult::UpdatedRsx(msgs) => { Ok(UpdateResult::UpdatedRsx(msgs)) => {
messages.extend(msgs); messages.extend(msgs);
} }
UpdateResult::NeedsRebuild => { Ok(UpdateResult::NeedsRebuild) => {
match build_manager.rebuild() { match build_manager.rebuild() {
Ok(res) => { Ok(res) => {
print_console_info( print_console_info(
@@ -242,6 +243,9 @@ pub async fn startup_hot_reload(
} }
return; return;
} }
Err(err) => {
log::error!("{}", err);
}
} }
} }
for msg in messages { for msg in messages {