From 972235bd6fba872c72a236e21fd4f5b855434d8f Mon Sep 17 00:00:00 2001 From: Benjamin Manns Date: Sun, 10 Dec 2023 13:16:59 -0500 Subject: [PATCH 01/10] Fix doc tests by adding formatting to CLI README (#1706) The README for cli gets included in lib.rs via `include_str!`. The code snippets then get assumed to be Rust, which fails if running `cargo test --doc`. This is not a huge problem, but was brought to my attention because Nix's `buildRustPackage` runs `cargo test` including doc tests (unlike what get run for this project on CI). This means I can't update the Nix package to 0.4.3 without changing the test flags (which I think I'll see about doing anyways, as that's how Dioxus runs CI). --- packages/cli/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cli/README.md b/packages/cli/README.md index 8379f22cc..2325d6784 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -10,7 +10,7 @@ It handles building, bundling, development and publishing to simplify developmen ### Install the stable version (recommended) -``` +```shell cargo install dioxus-cli ``` @@ -20,7 +20,7 @@ To get the latest bug fixes and features, you can install the development versio However, this is not fully tested. That means you're probably going to have more bugs despite having the latest bug fixes. -``` +```shell cargo install --git https://github.com/DioxusLabs/dioxus dioxus-cli ``` @@ -29,7 +29,7 @@ and install it in Cargo's global binary directory (`~/.cargo/bin/` by default). ### Install from local folder -``` +```shell cargo install --path . --debug ``` @@ -40,7 +40,7 @@ It will be cloned from the [dioxus-template](https://github.com/DioxusLabs/dioxu Alternatively, you can specify the template path: -``` +```shell dx create hello --template gh:dioxuslabs/dioxus-template ``` From 695bf009d11be0a8b717257ab2d56adf8873c489 Mon Sep 17 00:00:00 2001 From: YuKun Liu Date: Mon, 11 Dec 2023 11:27:55 -0800 Subject: [PATCH 02/10] fix: dx create not work (#1709) --- packages/cli/src/main.rs | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/packages/cli/src/main.rs b/packages/cli/src/main.rs index 7ca1b2c9a..2358551f2 100644 --- a/packages/cli/src/main.rs +++ b/packages/cli/src/main.rs @@ -42,34 +42,36 @@ async fn main() -> anyhow::Result<()> { set_up_logging(); - let bin = get_bin(args.bin)?; + let bin = get_bin(args.bin); - let _dioxus_config = DioxusConfig::load(Some(bin.clone())) + if let Ok(bin) = &bin { + let _dioxus_config = DioxusConfig::load(Some(bin.clone())) .map_err(|e| anyhow!("Failed to load Dioxus config because: {e}"))? .unwrap_or_else(|| { log::warn!("You appear to be creating a Dioxus project from scratch; we will use the default config"); DioxusConfig::default() }); - #[cfg(feature = "plugin")] - PluginManager::init(_dioxus_config.plugin) - .map_err(|e| anyhow!("🚫 Plugin system initialization failed: {e}"))?; + #[cfg(feature = "plugin")] + PluginManager::init(_dioxus_config.plugin) + .map_err(|e| anyhow!("🚫 Plugin system initialization failed: {e}"))?; + } match args.action { Translate(opts) => opts .translate() .map_err(|e| anyhow!("🚫 Translation of HTML into RSX failed: {}", e)), - Build(opts) => opts - .build(Some(bin.clone())) + Build(opts) if bin.is_ok() => opts + .build(Some(bin.unwrap().clone())) .map_err(|e| anyhow!("🚫 Building project failed: {}", e)), - Clean(opts) => opts - .clean(Some(bin.clone())) + Clean(opts) if bin.is_ok() => opts + .clean(Some(bin.unwrap().clone())) .map_err(|e| anyhow!("🚫 Cleaning project failed: {}", e)), - Serve(opts) => opts - .serve(Some(bin.clone())) + Serve(opts) if bin.is_ok() => opts + .serve(Some(bin.unwrap().clone())) .await .map_err(|e| anyhow!("🚫 Serving project failed: {}", e)), @@ -81,8 +83,8 @@ async fn main() -> anyhow::Result<()> { .config() .map_err(|e| anyhow!("🚫 Configuring new project failed: {}", e)), - Bundle(opts) => opts - .bundle(Some(bin.clone())) + Bundle(opts) if bin.is_ok() => opts + .bundle(Some(bin.unwrap().clone())) .map_err(|e| anyhow!("🚫 Bundling project failed: {}", e)), #[cfg(feature = "plugin")] @@ -107,5 +109,6 @@ async fn main() -> anyhow::Result<()> { Ok(()) } + _ => Err(anyhow::anyhow!(bin.unwrap_err())), } } From 0cb13942daffa8aa69a9a61aaa7982ea165d586f Mon Sep 17 00:00:00 2001 From: xfalcon Date: Wed, 13 Dec 2023 22:30:40 +0800 Subject: [PATCH 03/10] fix: command error with dx build --verbose (#1715) error msg: cannot set both --verbose and --quiet --- packages/cli/src/builder.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/builder.rs b/packages/cli/src/builder.rs index f7b6a3071..759be7dec 100644 --- a/packages/cli/src/builder.rs +++ b/packages/cli/src/builder.rs @@ -265,7 +265,6 @@ pub fn build_desktop(config: &CrateConfig, _is_serve: bool) -> Result Result Date: Wed, 13 Dec 2023 09:44:01 -0600 Subject: [PATCH 04/10] Autoformat ignores files in `.gitignore` (#1704) * Make autofmt ignore gitignored files * don't panic if it can't get the git ignore files * replace some with ok * Filter rs files from gitignore * fmt * remove early return * only ignore paths that start with target --------- Co-authored-by: Evan Almloff --- packages/cli/Cargo.toml | 1 + packages/cli/src/cli/autoformat.rs | 175 ++++++++++++++++------------- 2 files changed, 96 insertions(+), 80 deletions(-) diff --git a/packages/cli/Cargo.toml b/packages/cli/Cargo.toml index 128133602..4c115184e 100644 --- a/packages/cli/Cargo.toml +++ b/packages/cli/Cargo.toml @@ -83,6 +83,7 @@ dioxus-html = { workspace = true, features = ["hot-reload-context"] } dioxus-core = { workspace = true, features = ["serialize"] } dioxus-hot-reload = { workspace = true } interprocess-docfix = { version = "1.2.2" } +gitignore = "1.0.8" [features] default = [] diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index 6c1ce04a1..812a4c325 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -27,15 +27,17 @@ pub struct Autoformat { impl Autoformat { // Todo: autoformat the entire crate pub async fn autoformat(self) -> Result<()> { + let Autoformat { check, raw, file } = self; + // Default to formatting the project - if self.raw.is_none() && self.file.is_none() { - if let Err(e) = autoformat_project(self.check).await { + if raw.is_none() && file.is_none() { + if let Err(e) = autoformat_project(check).await { eprintln!("error formatting project: {}", e); exit(1); } } - if let Some(raw) = self.raw { + if let Some(raw) = raw { let indent = indentation_for(".")?; if let Some(inner) = dioxus_autofmt::fmt_block(&raw, 0, indent) { println!("{}", inner); @@ -47,47 +49,90 @@ impl Autoformat { } // Format single file - if let Some(file) = self.file { - let file_content; - let indent; - if file == "-" { - indent = indentation_for(".")?; - let mut contents = String::new(); - std::io::stdin().read_to_string(&mut contents)?; - file_content = Ok(contents); - } else { - indent = indentation_for(".")?; - file_content = fs::read_to_string(&file); - }; - - match file_content { - Ok(s) => { - let edits = dioxus_autofmt::fmt_file(&s, indent); - let out = dioxus_autofmt::apply_formats(&s, edits); - if file == "-" { - print!("{}", out); - } else { - match fs::write(&file, out) { - Ok(_) => { - println!("formatted {}", file); - } - Err(e) => { - eprintln!("failed to write formatted content to file: {}", e); - } - } - } - } - Err(e) => { - eprintln!("failed to open file: {}", e); - exit(1); - } - } + if let Some(file) = file { + refactor_file(file)?; } Ok(()) } } +fn refactor_file(file: String) -> Result<(), Error> { + let indent = indentation_for(".")?; + let file_content = if file == "-" { + let mut contents = String::new(); + std::io::stdin().read_to_string(&mut contents)?; + Ok(contents) + } else { + fs::read_to_string(&file) + }; + let Ok(s) = file_content else { + eprintln!("failed to open file: {}", file_content.unwrap_err()); + exit(1); + }; + let edits = dioxus_autofmt::fmt_file(&s, indent); + let out = dioxus_autofmt::apply_formats(&s, edits); + + if file == "-" { + print!("{}", out); + } else if let Err(e) = fs::write(&file, out) { + eprintln!("failed to write formatted content to file: {e}",); + } else { + println!("formatted {}", file); + } + + Ok(()) +} + +fn get_project_files(config: &CrateConfig) -> Vec { + let mut files = vec![]; + + let gitignore_path = config.crate_dir.join(".gitignore"); + if gitignore_path.is_file() { + let gitigno = gitignore::File::new(gitignore_path.as_path()).unwrap(); + if let Ok(git_files) = gitigno.included_files() { + let git_files = git_files + .into_iter() + .filter(|f| f.ends_with(".rs") && !is_target_dir(f)); + files.extend(git_files) + }; + } else { + collect_rs_files(&config.crate_dir, &mut files); + } + + files +} + +fn is_target_dir(file: &Path) -> bool { + let stripped = if let Ok(cwd) = std::env::current_dir() { + file.strip_prefix(cwd).unwrap_or(file) + } else { + file + }; + if let Some(first) = stripped.components().next() { + first.as_os_str() == "target" + } else { + false + } +} + +async fn format_file( + path: impl AsRef, + indent: IndentOptions, +) -> Result { + let contents = tokio::fs::read_to_string(&path).await?; + + let edits = dioxus_autofmt::fmt_file(&contents, indent); + let len = edits.len(); + + if !edits.is_empty() { + let out = dioxus_autofmt::apply_formats(&contents, edits); + tokio::fs::write(path, out).await?; + } + + Ok(len) +} + /// Read every .rs file accessible when considering the .gitignore and try to format it /// /// Runs using Tokio for multithreading, so it should be really really fast @@ -96,8 +141,7 @@ impl Autoformat { async fn autoformat_project(check: bool) -> Result<()> { let crate_config = crate::CrateConfig::new(None)?; - let mut files_to_format = vec![]; - collect_rs_files(&crate_config.crate_dir, &mut files_to_format); + let files_to_format = get_project_files(&crate_config); if files_to_format.is_empty() { return Ok(()); @@ -107,38 +151,17 @@ async fn autoformat_project(check: bool) -> Result<()> { let counts = files_to_format .into_iter() - .filter(|file| { - if file.components().any(|f| f.as_os_str() == "target") { - return false; - } - - true - }) .map(|path| async { - let _path = path.clone(); - let _indent = indent.clone(); - let res = tokio::spawn(async move { - let contents = tokio::fs::read_to_string(&path).await?; - - let edits = dioxus_autofmt::fmt_file(&contents, _indent.clone()); - let len = edits.len(); - - if !edits.is_empty() { - let out = dioxus_autofmt::apply_formats(&contents, edits); - tokio::fs::write(&path, out).await?; - } - - Ok(len) as Result - }) - .await; + let path_clone = path.clone(); + let res = tokio::spawn(format_file(path, indent.clone())).await; match res { Err(err) => { - eprintln!("error formatting file: {}\n{err}", _path.display()); + eprintln!("error formatting file: {}\n{err}", path_clone.display()); None } Ok(Err(err)) => { - eprintln!("error formatting file: {}\n{err}", _path.display()); + eprintln!("error formatting file: {}\n{err}", path_clone.display()); None } Ok(Ok(res)) => Some(res), @@ -148,13 +171,7 @@ async fn autoformat_project(check: bool) -> Result<()> { .collect::>() .await; - let files_formatted: usize = counts - .into_iter() - .map(|f| match f { - Some(res) => res, - _ => 0, - }) - .sum(); + let files_formatted: usize = counts.into_iter().flatten().sum(); if files_formatted > 0 && check { eprintln!("{} files needed formatting", files_formatted); @@ -207,26 +224,24 @@ fn indentation_for(file_or_dir: impl AsRef) -> Result { )) } -fn collect_rs_files(folder: &Path, files: &mut Vec) { - let Ok(folder) = folder.read_dir() else { +fn collect_rs_files(folder: &impl AsRef, files: &mut Vec) { + if is_target_dir(folder.as_ref()) { + return; + } + let Ok(folder) = folder.as_ref().read_dir() else { return; }; - // load the gitignore - for entry in folder { let Ok(entry) = entry else { continue; }; - let path = entry.path(); - if path.is_dir() { collect_rs_files(&path, files); } - if let Some(ext) = path.extension() { - if ext == "rs" { + if ext == "rs" && !is_target_dir(&path) { files.push(path); } } From 2321c1ad4448aa8b2759972fa695a9944bc8c203 Mon Sep 17 00:00:00 2001 From: w3irdrobot <3712883+w3irdrobot@users.noreply.github.com> Date: Fri, 15 Dec 2023 18:55:19 -0500 Subject: [PATCH 05/10] add error log when root element isn't found (#1724) --- packages/web/Cargo.toml | 1 + packages/web/src/dom.rs | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/web/Cargo.toml b/packages/web/Cargo.toml index 35eb9c5f1..b2a8e94c8 100644 --- a/packages/web/Cargo.toml +++ b/packages/web/Cargo.toml @@ -42,6 +42,7 @@ features = [ "HtmlFormElement", "Text", "Window", + "console", ] [features] diff --git a/packages/web/src/dom.rs b/packages/web/src/dom.rs index f45d6558a..b8e9255f7 100644 --- a/packages/web/src/dom.rs +++ b/packages/web/src/dom.rs @@ -45,7 +45,16 @@ impl WebsysDom { let document = load_document(); let root = match document.get_element_by_id(&cfg.rootname) { Some(root) => root, - None => document.create_element("body").ok().unwrap(), + None => { + web_sys::console::error_1( + &format!( + "element '#{}' not found. mounting to the body.", + cfg.rootname + ) + .into(), + ); + document.create_element("body").ok().unwrap() + } }; let interpreter = Channel::default(); From cf413780c1a00240ec9eaf9f4bd19c09119f5250 Mon Sep 17 00:00:00 2001 From: Exotik850 <60969639+Exotik850@users.noreply.github.com> Date: Sun, 17 Dec 2023 15:26:40 -0600 Subject: [PATCH 06/10] Make hot reload error only show once (#1725) --- packages/cli/src/server/desktop/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/server/desktop/mod.rs b/packages/cli/src/server/desktop/mod.rs index fec1e5a99..97f316d3c 100644 --- a/packages/cli/src/server/desktop/mod.rs +++ b/packages/cli/src/server/desktop/mod.rs @@ -127,6 +127,7 @@ async fn start_desktop_hot_reload(hot_reload_state: HotReloadState) -> Result<() let file_map = hot_reload_state.file_map.clone(); let channels = channels.clone(); let aborted = aborted.clone(); + let mut error_shown = false; move || { loop { //accept() will block the thread when local_socket_stream is in blocking mode (default) @@ -154,7 +155,8 @@ async fn start_desktop_hot_reload(hot_reload_state: HotReloadState) -> Result<() println!("Connected to hot reloading 🚀"); } Err(err) => { - if err.kind() != std::io::ErrorKind::WouldBlock { + if !error_shown && err.kind() != std::io::ErrorKind::WouldBlock { + error_shown = true; println!("Error connecting to hot reloading: {} (Hot reloading is a feature of the dioxus-cli. If you are not using the CLI, this error can be ignored)", err); } } From e7515d18c1eef6f8547ea7e3ee1137561fdbb165 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Sun, 17 Dec 2023 15:39:48 -0600 Subject: [PATCH 07/10] show multiple different error messages in hot reloading --- packages/cli/src/server/desktop/mod.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/server/desktop/mod.rs b/packages/cli/src/server/desktop/mod.rs index 97f316d3c..c89fb858c 100644 --- a/packages/cli/src/server/desktop/mod.rs +++ b/packages/cli/src/server/desktop/mod.rs @@ -7,10 +7,11 @@ use crate::{ }; use dioxus_hot_reload::HotReloadMsg; -use dioxus_html::HtmlCtx; +use dioxus_html::{HtmlCtx, SvgAttributes}; use dioxus_rsx::hot_reload::*; use interprocess_docfix::local_socket::LocalSocketListener; use std::{ + collections::HashSet, process::{Child, Command}, sync::{Arc, Mutex, RwLock}, }; @@ -127,7 +128,6 @@ async fn start_desktop_hot_reload(hot_reload_state: HotReloadState) -> Result<() let file_map = hot_reload_state.file_map.clone(); let channels = channels.clone(); let aborted = aborted.clone(); - let mut error_shown = false; move || { loop { //accept() will block the thread when local_socket_stream is in blocking mode (default) @@ -155,8 +155,11 @@ async fn start_desktop_hot_reload(hot_reload_state: HotReloadState) -> Result<() println!("Connected to hot reloading 🚀"); } Err(err) => { - if !error_shown && err.kind() != std::io::ErrorKind::WouldBlock { - error_shown = true; + let error_string = err.to_string(); + // Filter out any error messages about a operation that may block and an error message that triggers on some operating systems that says "Waiting for a process to open the other end of the pipe" without WouldBlock being set + let display_error = err.kind() != std::io::ErrorKind::WouldBlock + && !error_string.contains("Waiting for a process"); + if display_error { println!("Error connecting to hot reloading: {} (Hot reloading is a feature of the dioxus-cli. If you are not using the CLI, this error can be ignored)", err); } } From 2a764aaf6a3854469a005e533b5dc8547116ca1e Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Sun, 17 Dec 2023 15:42:58 -0600 Subject: [PATCH 08/10] remove some unused CLI imports --- packages/cli/src/server/desktop/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/cli/src/server/desktop/mod.rs b/packages/cli/src/server/desktop/mod.rs index c89fb858c..ec21fa4c0 100644 --- a/packages/cli/src/server/desktop/mod.rs +++ b/packages/cli/src/server/desktop/mod.rs @@ -7,11 +7,10 @@ use crate::{ }; use dioxus_hot_reload::HotReloadMsg; -use dioxus_html::{HtmlCtx, SvgAttributes}; +use dioxus_html::HtmlCtx; use dioxus_rsx::hot_reload::*; use interprocess_docfix::local_socket::LocalSocketListener; use std::{ - collections::HashSet, process::{Child, Command}, sync::{Arc, Mutex, RwLock}, }; From cd019db9ef89a39bf58e33064a4f32b370018acb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 08:04:53 -0600 Subject: [PATCH 09/10] Bump actions/upload-artifact from 3 to 4 (#1726) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/playwright.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index cb5a1f1bb..7b23c6111 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -43,7 +43,7 @@ jobs: # args: --path packages/cli - name: Run Playwright tests run: npx playwright test - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 if: always() with: name: playwright-report From 1880bdb308c15233a78cf313190ec41254137b93 Mon Sep 17 00:00:00 2001 From: ealmloff Date: Wed, 20 Dec 2023 10:28:24 -0600 Subject: [PATCH 10/10] Remove link to Tide's contributing guidelines --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d1ec98019..65cd08263 100644 --- a/README.md +++ b/README.md @@ -161,7 +161,7 @@ So... Dioxus is great, but why won't it work for me? ## Contributing - Check out the website [section on contributing](https://dioxuslabs.com/learn/0.4/contributing). - Report issues on our [issue tracker](https://github.com/dioxuslabs/dioxus/issues). -- Join the discord and ask questions! +- [Join](https://discord.gg/XgGxMSkvUM) the discord and ask questions!