Merge pull request #156 from Demonthos/create-dioxus-app
Make Dioxus create interactive
This commit is contained in:
7 files changed
+1381
-516
No files matched your search
Generated
+1311
-443
File diff suppressed because it is too large.
Load diff
+8
-6
@@ -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
@@ -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
@@ -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
|
||||||
}
|
}
|
||||||
@@ -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},
|
||||||
|
|||||||
@@ -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
@@ -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 {
|
||||||
|
|||||||
Reference in new issue
Block a user