Prechádzať zdrojové kódy

Merge branch 'intigrate-collect-assets' of https://github.com/Demonthos/dioxus into intigrate-collect-assets

Evan Almloff 1 rok pred
rodič
commit
0914298bea

+ 1 - 1
.github/workflows/playwright.yml

@@ -44,7 +44,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

+ 1 - 1
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!
 
 
 <a href="https://github.com/dioxuslabs/dioxus/graphs/contributors">

+ 1 - 0
packages/cli/Cargo.toml

@@ -85,6 +85,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 = []

+ 4 - 4
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
 ```
 

+ 2 - 1
packages/cli/src/builder.rs

@@ -280,7 +280,6 @@ pub fn build_desktop(
         .env("CARGO_TARGET_DIR", &config.target_dir)
         .cwd(&config.crate_dir)
         .arg("build")
-        .arg("--quiet")
         .arg("--message-format=json");
 
     if config.release {
@@ -288,6 +287,8 @@ pub fn build_desktop(
     }
     if config.verbose {
         cmd = cmd.arg("--verbose");
+    } else {
+        cmd = cmd.arg("--quiet");
     }
 
     if config.custom_profile.is_some() {

+ 95 - 80
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<PathBuf> {
+    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<Path>,
+    indent: IndentOptions,
+) -> Result<usize, tokio::io::Error> {
+    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<usize, tokio::io::Error>
-            })
-            .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::<Vec<_>>()
         .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<Path>) -> Result<IndentOptions> {
     ))
 }
 
-fn collect_rs_files(folder: &Path, files: &mut Vec<PathBuf>) {
-    let Ok(folder) = folder.read_dir() else {
+fn collect_rs_files(folder: &impl AsRef<Path>, files: &mut Vec<PathBuf>) {
+    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);
             }
         }

+ 16 - 13
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()), None)
+        Build(opts) if bin.is_ok() => opts
+            .build(Some(bin.unwrap().clone()), None)
             .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())),
     }
 }

+ 5 - 1
packages/cli/src/server/desktop/mod.rs

@@ -147,7 +147,11 @@ 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 {
+                                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);
                                 }
                             }

+ 1 - 0
packages/web/Cargo.toml

@@ -42,6 +42,7 @@ features = [
     "HtmlFormElement",
     "Text",
     "Window",
+    "console",
 ]
 
 [features]

+ 10 - 1
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();