Merge branch 'master' into intigrate-collect-assets

This commit is contained in:
Evan Almloff committed 2023-10-10 09:57:16 -05:00
1 parent e5b15f7c31
commit b76f129083
55 files changed
+213 -5697

No files matched your search

+1 -1
View File
@@ -2,7 +2,7 @@
target/
**/*.rs.bk
# tauri-mobile
# cargo-mobile2
.cargo/
/gen
+1 -1
View File
@@ -4,7 +4,7 @@
Right now, Dioxus supports mobile targets including iOS and Android. However, our tooling is not mature enough to include the build commands directly.
This project was generated using [tauri-mobile](https://github.com/tauri-apps/tauri-mobile). We have yet to integrate this generation into the Dioxus-CLI. The open issue for this is [#1157](https://github.com/DioxusLabs/dioxus/issues/1157).
This project was generated using [cargo-mobile2](https://github.com/tauri-apps/cargo-mobile2). We have yet to integrate this generation into the Dioxus-CLI. The open issue for this is [#1157](https://github.com/DioxusLabs/dioxus/issues/1157).
## Running on iOS
-3
View File
@@ -11,13 +11,10 @@ keywords = ["dom", "ui", "gui", "react"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dioxus-rsx = { workspace = true }
proc-macro2 = { version = "1.0.6", features = ["span-locations"] }
quote = "1.0"
syn = { version = "1.0.11", features = ["full", "extra-traits", "visit"] }
serde = { version = "1.0.136", features = ["derive"] }
owo-colors = { version = "3.5.0", features = ["supports-colors"] }
prettyplease = { workspace = true }
[dev-dependencies]
indoc = "2.0.3"
-31
View File
@@ -1,31 +0,0 @@
# .github/workflows/build.yml
on:
release:
types: [created]
jobs:
release:
name: release ${{ matrix.target }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
archive: tar.gz tar.xz
- target: x86_64-unknown-linux-musl
archive: tar.gz tar.xz
- target: x86_64-apple-darwin
archive: tar.gz tar.xz
- target: x86_64-pc-windows-gnu
archive: zip
steps:
- uses: actions/checkout@master
- name: Compile and release
uses: rust-build/rust-build.action@latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RUSTTARGET: ${{ matrix.target }}
ARCHIVE_TYPES: ${{ matrix.archive }}
-34
View File
@@ -1,34 +0,0 @@
name: github pages
on:
push:
paths:
- docs/**
branches:
- master
jobs:
deploy:
runs-on: ubuntu-20.04
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
steps:
- uses: actions/checkout@v2
- name: Setup mdBook
uses: peaceiris/actions-mdbook@v1
with:
mdbook-version: '0.4.10'
# mdbook-version: 'latest'
- run: cd docs && mdbook build
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@v4.2.3
with:
branch: gh-pages # The branch the action should deploy to.
folder: docs/book # The folder the action should deploy.
target-folder: docs/nightly/cli
repository-name: dioxuslabs/docsite
clean: false
token: ${{ secrets.DEPLOY_KEY }} # let's pretend I don't need it for now
-52
View File
@@ -1,52 +0,0 @@
on: [push, pull_request]
name: Rust CI
jobs:
check:
name: Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v1
- run: cargo check
test:
name: Test Suite
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v1
- run: cargo test
fmt:
name: Rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v1
- run: rustup component add rustfmt
- run: cargo fmt --all -- --check
# clippy:
# name: Clippy
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v2
# - uses: actions-rs/toolchain@v1
# with:
# profile: minimal
# toolchain: stable
# override: true
# - uses: Swatinem/rust-cache@v1
# - run: rustup component add clippy
# - uses: actions-rs/cargo@v1
# with:
# command: clippy
# args: -- -D warnings
-4778
View File
File diff suppressed because it is too large. Load diff
+1 -6
View File
@@ -26,12 +26,9 @@ cargo_toml = "0.16.0"
futures = "0.3.21"
notify = { version = "5.0.0-pre.16", features = ["serde"] }
html_parser = { workspace = true }
binary-install = "0.0.2"
convert_case = "0.5.0"
cargo_metadata = "0.15.0"
tokio = { version = "1.16.1", features = ["full"] }
tokio = { version = "1.16.1", features = ["fs", "sync", "rt", "macros"] }
atty = "0.2.14"
regex = "1.5.4"
chrono = "0.4.19"
anyhow = "1"
hyper = "0.14.17"
@@ -59,7 +56,6 @@ tar = "0.4.38"
zip = "0.6.2"
tower = "0.4.12"
syn = { version = "2.0", features = ["full", "extra-traits"] }
proc-macro2 = { version = "1.0", features = ["span-locations"] }
lazy_static = "1.4.0"
# plugin packages
@@ -71,7 +67,6 @@ mlua = { version = "0.8.1", features = [
"macros",
], optional = true }
ctrlc = "3.2.3"
gitignore = "1.0.7"
open = "4.1.0"
cargo-generate = "0.18"
toml_edit = "0.19.11"
+1 -1
View File
@@ -4,7 +4,7 @@
</div>
The **dioxus-cli** (inspired by wasm-pack and webpack) is a tool for getting Dioxus projects up and running.
It handles all building, bundling, development and publishing to simplify development.
It handles building, bundling, development and publishing to simplify development.
## Installation
-1
View File
@@ -1 +0,0 @@
book
-6
View File
@@ -1,6 +0,0 @@
[book]
authors = ["YuKun Liu"]
language = "en"
multilingual = false
src = "src"
title = "Dioxus CLI"
-13
View File
@@ -1,13 +0,0 @@
# Summary
- [Introduction](./introduction.md)
- [Installation](./installation.md)
- [Create a project](./creating.md)
- [Configure a project](./configure.md)
- [Plugin development](./plugin/README.md)
- [API.Log](plugin/interface/log.md)
- [API.Command](plugin/interface/command.md)
- [API.OS](plugin/interface/os.md)
- [API.Directories](plugin/interface/dirs.md)
- [API.Network](plugin/interface/network.md)
- [API.Path](plugin/interface/path.md)
-197
View File
@@ -1,197 +0,0 @@
# Configure Project
This chapter will teach you how to configure the CLI with the `Dioxus.toml` file.
There's an [example](#config-example) which has comments to describe individual keys.
You can copy that or view this documentation for a more complete learning experience.
"🔒" indicates a mandatory item. Some headers are mandatory, but none of the keys inside them are. It might look weird, but it's normal. Simply don't include any keys.
## Structure
Each header has it's TOML form directly under it.
### Application 🔒
```toml
[application]
```
Application-wide configuration. Applies to both web and desktop.
1. **name** 🔒 - Project name & title.
```toml
name = "my_project"
```
2. **default_platform** 🔒 - The platform this project targets
```toml
# Currently supported platforms: web, desktop
default_platform = "web"
```
3. **out_dir** - The directory to place the build artifacts from `dx build` or `dx serve` into. This is also where the `assets` directory will be copied into.
```toml
out_dir = "dist"
```
4. **asset_dir** - The directory with your static assets. The CLI will automatically copy these assets into the **out_dir** after a build/serve.
```toml
asset_dir = "public"
```
5. **sub_package** - The sub package in the workspace to build by default.
```toml
sub_package = "my-crate"
```
### Web.App 🔒
```toml
[web.app]
```
Web-specific configuration.
1. **title** - The title of the web page.
```toml
# HTML title tag content
title = "project_name"
```
2. **base_path** - The base path to build the application for serving at. This can be useful when serving your application in a subdirectory under a domain. For example when building a site to be served on GitHub Pages.
```toml
# The application will be served at domain.com/my_application/, so we need to modify the base_path to the path where the application will be served
base_path = "my_application"
```
### Web.Watcher ✍
```toml
[web.watcher]
```
Development server configuration.
1. **reload_html** - If this is true, the cli will rebuild the index.html file every time the application is rebuilt
```toml
reload_html = true
```
2. **watch_path** - The files & directories to monitor for changes
```toml
watch_path = ["src", "public"]
```
3. **index_on_404** - If enabled, Dioxus will serve the root page when a route is not found.
*This is needed when serving an application that uses the router*.
However, when serving your app using something else than Dioxus (e.g. GitHub Pages), you will have to check how to configure it on that platform.
In GitHub Pages, you can make a copy of `index.html` named `404.html` in the same directory.
```toml
index_on_404 = true
```
### Web.Resource 🔒
```toml
[web.resource]
```
Static resource configuration.
1. **style** - CSS files to include in your application.
```toml
style = [
# Include from public_dir.
"./assets/style.css",
# Or some asset from online cdn.
"https://cdn.jsdelivr.net/npm/bootstrap/dist/css/bootstrap.css"
]
```
2. **script** - JavaScript files to include in your application.
```toml
script = [
# Include from asset_dir.
"./public/index.js",
# Or from an online CDN.
"https://cdn.jsdelivr.net/npm/bootstrap/dist/js/bootstrap.js"
]
```
### Web.Resource.Dev 🔒
```toml
[web.resource.dev]
```
This is the same as [`[web.resource]`](#webresource-), but it only works in development servers.
For example, if you want to include a file in a `dx serve` server, but not a `dx serve --release` server, put it here.
### Web.Proxy
```toml
[[web.proxy]]
```
Configuration related to any proxies your application requires during development. Proxies will forward requests to a new service.
1. **backend** - The URL to the server to proxy. The CLI will forward any requests under the backend relative route to the backend instead of returning 404
```toml
backend = "http://localhost:8000/api/"
```
This will cause any requests made to the dev server with prefix /api/ to be redirected to the backend server at http://localhost:8000. The path and query parameters will be passed on as-is (path rewriting is currently not supported).
## Config example
This includes all fields, mandatory or not.
```toml
[application]
# App name
name = "project_name"
# The Dioxus platform to default to
default_platform = "web"
# `build` & `serve` output path
out_dir = "dist"
# The static resource path
asset_dir = "public"
[web.app]
# HTML title tag content
title = "project_name"
[web.watcher]
# When watcher is triggered, regenerate the `index.html`
reload_html = true
# Which files or dirs will be monitored
watch_path = ["src", "public"]
# Include style or script assets
[web.resource]
# CSS style file
style = []
# Javascript code file
script = []
[web.resource.dev]
# Same as [web.resource], but for development servers
# CSS style file
style = []
# JavaScript files
script = []
[[web.proxy]]
backend = "http://localhost:8000/api/"
```
-37
View File
@@ -1,37 +0,0 @@
# Create a Project
Once you have the Dioxus CLI installed, you can use it to create your own project!
## Initializing a default project
First, run the `dx create` command to create a new project:
```
dx create hello-dioxus
```
> It will clone this [template](https://github.com/DioxusLabs/dioxus-template).
> This default template is used for `web` platform application.
>
> You can choose to create your project from a different template by passing the `template` argument:
> ```
> dx init hello-dioxus --template=gh:dioxuslabs/dioxus-template
> ```
Next, navigate into your new project:
```
cd hello-dioxus
```
> Make sure the WASM target is installed before running the projects.
> You can install the WASM target for rust using rustup:
> ```
> rustup target add wasm32-unknown-unknown
> ```
Finally, serve your project:
```
dx serve
```
By default, the CLI serves your website at [`http://127.0.0.1:8080/`](http://127.0.0.1:8080/).
-23
View File
@@ -1,23 +0,0 @@
# Installation
## Install the latest development build through git
To get the latest bug fixes and features, you can install the development version from git.
```
cargo install --git https://github.com/Dioxuslabs/cli
```
This will download `Dioxus-CLI` source from GitHub master branch,
and install it in Cargo's global binary directory (`~/.cargo/bin/` by default).
## Install stable through `crates.io`
The published version of the Dioxus CLI is updated less often, but is more stable than the git version.
```
cargo install dioxus-cli --locked
```
Run `dx --help` for a list of all the available commands.
Furthermore, you can run `dx <COMMAND> --help` to get help with a specific command.
-18
View File
@@ -1,18 +0,0 @@
# Introduction
The 📦✨ **Dioxus CLI** is a tool to help get Dioxus projects off the ground.
## Features
* Build and pack a Dioxus project
* `html` to `rsx` conversion tool
* Hot Reload for `web` platform
* Create a Dioxus project from `git` repo
* And more!
<!-- Checkmarks don't render on the website, so I've just made a normal list. You can uncomment this if the website rendering is fixed.
- [x] `html` to `rsx` conversion tool
- [x] Hot Reload for `web` platform
- [x] Create a Dioxus project from `git` repo
- [x] Build & pack Dioxus project
- [ ] Automatically format Dioxus `rsx` code
-->
-140
View File
@@ -1,140 +0,0 @@
# CLI Plugin development
**IMPORTANT: Ignore this documentation. Plugins are yet to be released and chances are it won't work for you. This is just what plugins *could* look like.**
In the past we used `dx tool` to use and install tools, but it was a flawed system.
Tools were hard-coded by us, but people want more tools than we could code, so this plugin system was made to let
anyone develop plugins and use them in Dioxus projects.
Plugin resources:
* [Source code](https://github.com/DioxusLabs/dioxus/tree/master/packages/cli/src/plugin)
* [Unofficial Dioxus plugin community](https://github.com/DioxusPluginCommunity). Contains certain plugins you can use right now.
### Why Lua?
We chose Lua `5.4` to be the plugin developing language,
because it's extremely lightweight, embeddable and easy to learn.
We installed Lua into the CLI, so you don't need to do it yourself.
Lua resources:
* [Official website](https://www.lua.org/). You can basically find everything here.
* [Awesome Lua](https://github.com/LewisJEllis/awesome-lua). Additional resources (such as Lua plugins for your favorite IDE), and other *awesome* tools!
## Creating a plugin
A plugin is just an `init.lua` file.
You can include other files using `dofile(path)`.
You need to have a plugin and a manager instance, which you can get using `require`:
```lua
local plugin = require("plugin")
local manager = require("manager")
```
You need to set some `manager` fields and then initialize the plugin:
```lua
manager.name = "My first plugin"
manager.repository = "https://github.com/john-doe/my-first-plugin" -- The repository URL.
manager.author = "John Doe <john.doe@example.com>"
manager.version = "0.1.0"
plugin.init(manager)
```
You also need to return the `manager`, which basically represents your plugin:
```lua
-- Your code here.
-- End of file.
manager.serve.interval = 1000
return manager
```
And you're ready to go. Now, go and have a look at the stuff below and the API documentation.
### Plugin info
You will encounter this type in the events below. The keys are as follows:
* `name: string` - The name of the plugin.
* `repository: string` - The plugin repository URL.
* `author: string` - The author of the plugin.
* `version: string` - The plugin version.
### Event management
The plugin library has certain events that you can subscribe to.
* `manager.on_init` - Triggers the first time the plugin is loaded.
* `manager.build.on_start(info)` - Triggers before the build process. E.g., before `dx build`.
* `manager.build.on_finish(info)` - Triggers after the build process. E.g., after `dx build`.
* `manager.serve.on_start(info)` - Triggers before the serving process. E.g., before `dx serve`.
* `manager.serve.on_rebuild_start(info)` - Triggers before the server rebuilds the web with hot reload.
* `manager.serve.on_rebuild_end(info)` - Triggers after the server rebuilds the web with hot reload.
* `manager.serve.on_shutdown` - Triggers when the server is shutdown. E.g., when the `dx serve` process is terminated.
To subscribe to an event, you simply need to assign it to a function:
```lua
manager.build.on_start = function (info)
log.info("[plugin] Build starting: " .. info.name)
end
```
### Plugin template
```lua
package.path = library_dir .. "/?.lua"
local plugin = require("plugin")
local manager = require("manager")
-- deconstruct api functions
local log = plugin.log
-- plugin information
manager.name = "Hello Dixous Plugin"
manager.repository = "https://github.com/mrxiaozhuox/hello-dioxus-plugin"
manager.author = "YuKun Liu <mrxzx.info@gmail.com>"
manager.version = "0.0.1"
-- init manager info to plugin api
plugin.init(manager)
manager.on_init = function ()
-- when the first time plugin been load, this function will be execute.
-- system will create a `dcp.json` file to verify init state.
log.info("[plugin] Start to init plugin: " .. manager.name)
end
---@param info BuildInfo
manager.build.on_start = function (info)
-- before the build work start, system will execute this function.
log.info("[plugin] Build starting: " .. info.name)
end
---@param info BuildInfo
manager.build.on_finish = function (info)
-- when the build work is done, system will execute this function.
log.info("[plugin] Build finished: " .. info.name)
end
---@param info ServeStartInfo
manager.serve.on_start = function (info)
-- this function will after clean & print to run, so you can print some thing.
log.info("[plugin] Serve start: " .. info.name)
end
---@param info ServeRebuildInfo
manager.serve.on_rebuild = function (info)
-- this function will after clean & print to run, so you can print some thing.
local files = plugin.tool.dump(info.changed_files)
log.info("[plugin] Serve rebuild: '" .. files .. "'")
end
manager.serve.on_shutdown = function ()
log.info("[plugin] Serve shutdown")
end
manager.serve.interval = 1000
return manager
```
@@ -1,21 +0,0 @@
# Command Functions
You can use command functions to execute code and scripts.
Type definition:
```
Stdio: "Inherit" | "Piped" | "Null"
```
### `exec(commands: [string], stdout: Stdio, stderr: Stdio)`
You can use this function to run some commands on the current system.
```lua
local cmd = plugin.command
manager.test = function ()
cmd.exec({"git", "clone", "https://github.com/DioxusLabs/cli-plugin-library"})
end
```
> Warning: This function doesn't catch exceptions.
@@ -1,30 +0,0 @@
# Dirs Functions
Dirs functions are for getting various directory paths. Not to be confused with `plugin.path`.
### `plugin_dir() -> string`
Get the plugin's root directory path.
```lua
local path = plugin.dirs.plugin_dir()
-- example: ~/Development/DioxusCli/plugin/test-plugin/
```
### `bin_dir() -> string`
Get the plugin's binary directory path. Put binary files like `tailwind-cli` or `sass-cli` in this directory.
```lua
local path = plugin.dirs.bin_dir()
-- example: ~/Development/DioxusCli/plugin/test-plugin/bin/
```
### `temp_dir() -> string`
Get the plugin's temporary directory path. Put any temporary files here.
```lua
local path = plugin.dirs.bin_dir()
-- example: ~/Development/DioxusCli/plugin/test-plugin/temp/
```
@@ -1,48 +0,0 @@
# Log Functions
You can use log functions to print various logging information.
### `trace(info: string)`
Print trace log info.
```lua
local log = plugin.log
log.trace("trace information")
```
### `debug(info: string)`
Print debug log info.
```lua
local log = plugin.log
log.debug("debug information")
```
### `info(info: string)`
Print info log info.
```lua
local log = plugin.log
log.info("info information")
```
### `warn(info: string)`
Print warning log info.
```lua
local log = plugin.log
log.warn("warn information")
```
### `error(info: string)`
Print error log info.
```lua
local log = plugin.log
log.error("error information")
```
@@ -1,37 +0,0 @@
# Network Functions
You can use Network functions to download & read some data from the internet.
### `download_file(url: string, path: string) -> boolean`
Downloads a file from the specified URL,
and returns a `boolean` that represents the download status (true: success, false: failure).
You need to pass a target URL and a local path (where you want to save this file).
```lua
-- this file will download to plugin temp directory
local status = plugin.network.download_file(
"http://xxx.com/xxx.zip",
plugin.dirs.temp_dir()
)
if status != true then
log.error("Download Failed")
end
```
### `clone_repo(url: string, path: string) -> boolean`
Clone a repository from the given URL into the given path.
Returns a `boolean` that represents the clone status (true: success, false: failure).
The system executing this function must have git installed.
```lua
local status = plugin.network.clone_repo(
"http://github.com/mrxiaozhuox/dioxus-starter",
plugin.dirs.bin_dir()
)
if status != true then
log.error("Clone Failed")
end
```
@@ -1,11 +0,0 @@
# OS Functions
OS functions are for getting system information.
### `current_platform() -> string ("windows" | "macos" | "linux")`
Get the current OS platform.
```lua
local platform = plugin.os.current_platform()
```
@@ -1,38 +0,0 @@
# Path Functions
You can use path functions to perform operations on valid path strings.
### `join(path: string, extra: string) -> string`
<!-- TODO: Add specifics.
From the example given, it seems like it just creates a subdirectory path.
What would it do when "extending" file paths? -->
Extend a path; you can extend both directory and file paths.
```lua
local current_path = "~/hello/dioxus"
local new_path = plugin.path.join(current_path, "world")
-- new_path = "~/hello/dioxus/world"
```
### `parent(path: string) -> string`
Return the parent path of the specified path. The parent path is always a directory.
```lua
local current_path = "~/hello/dioxus"
local new_path = plugin.path.parent(current_path)
-- new_path = "~/hello/"
```
### `exists(path: string) -> boolean`
Check if the specified path exists, as either a file or a directory.
### `is_file(path: string) -> boolean`
Check if the specified path is a file.
### `is_dir(path: string) -> boolean`
Check if the specified path is a directory.
-18
View File
@@ -1,18 +0,0 @@
local Api = require("./interface")
local log = Api.log;
local manager = {
name = "Dioxus-CLI Plugin Demo",
repository = "http://github.com/DioxusLabs/cli",
author = "YuKun Liu <mrxzx.info@gmail.com>",
}
manager.onLoad = function ()
log.info("plugin loaded.")
end
manager.onStartBuild = function ()
log.warn("system start to build")
end
return manager
@@ -1,25 +0,0 @@
local interface = {}
if plugin_logger ~= nil then
interface.log = plugin_logger
else
interface.log = {
trace = function (info)
print("trace: " .. info)
end,
debug = function (info)
print("debug: " .. info)
end,
info = function (info)
print("info: " .. info)
end,
warn = function (info)
print("warn: " .. info)
end,
error = function (info)
print("error: " .. info)
end,
}
end
return interface
-33
View File
@@ -719,7 +719,6 @@ fn build_assets(config: &CrateConfig) -> Result<Vec<PathBuf>> {
Ok(result)
}
/// Process any assets collected from the binary
fn process_assets(config: &CrateConfig) -> anyhow::Result<()> {
let manifest = config.asset_manifest();
@@ -740,38 +739,6 @@ fn process_assets(config: &CrateConfig) -> anyhow::Result<()> {
Ok(())
}
// use binary_install::{Cache, Download};
// /// Attempts to find `wasm-opt` in `PATH` locally, or failing that downloads a
// /// precompiled binary.
// ///
// /// Returns `Some` if a binary was found or it was successfully downloaded.
// /// Returns `None` if a binary wasn't found in `PATH` and this platform doesn't
// /// have precompiled binaries. Returns an error if we failed to download the
// /// binary.
// pub fn find_wasm_opt(
// cache: &Cache,
// install_permitted: bool,
// ) -> Result<install::Status, failure::Error> {
// // First attempt to look up in PATH. If found assume it works.
// if let Ok(path) = which::which("wasm-opt") {
// PBAR.info(&format!("found wasm-opt at {:?}", path));
// match path.as_path().parent() {
// Some(path) => return Ok(install::Status::Found(Download::at(path))),
// None => {}
// }
// }
// let version = "version_78";
// Ok(install::download_prebuilt(
// &install::Tool::WasmOpt,
// cache,
// version,
// install_permitted,
// )?)
// }
pub(crate) struct WebAssetConfigDropGuard;
impl WebAssetConfigDropGuard {
+17 -7
View File
@@ -46,18 +46,28 @@ impl Autoformat {
// Format single file
if let Some(file) = self.file {
let file_content = fs::read_to_string(&file);
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)
};
match file_content {
Ok(s) => {
let edits = dioxus_autofmt::fmt_file(&s);
let out = dioxus_autofmt::apply_formats(&s, edits);
match fs::write(&file, out) {
Ok(_) => {
println!("formatted {}", file);
}
Err(e) => {
eprintln!("failed to write formatted content to file: {}", e);
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);
}
}
}
}
+26 -19
View File
@@ -118,27 +118,34 @@ async fn start_desktop_hot_reload(hot_reload_state: HotReloadState) -> Result<()
let _ = local_socket_stream.set_nonblocking(true);
move || {
loop {
if let Ok(mut connection) = local_socket_stream.accept() {
// send any templates than have changed before the socket connected
let templates: Vec<_> = {
file_map
.lock()
.unwrap()
.map
.values()
.filter_map(|(_, template_slot)| *template_slot)
.collect()
};
for template in templates {
if !send_msg(
HotReloadMsg::UpdateTemplate(template),
&mut connection,
) {
continue;
match local_socket_stream.accept() {
Ok(mut connection) => {
// send any templates than have changed before the socket connected
let templates: Vec<_> = {
file_map
.lock()
.unwrap()
.map
.values()
.filter_map(|(_, template_slot)| *template_slot)
.collect()
};
for template in templates {
if !send_msg(
HotReloadMsg::UpdateTemplate(template),
&mut connection,
) {
continue;
}
}
channels.lock().unwrap().push(connection);
println!("Connected to hot reloading 🚀");
}
Err(err) => {
if err.kind() != std::io::ErrorKind::WouldBlock {
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);
}
}
channels.lock().unwrap().push(connection);
println!("Connected to hot reloading 🚀");
}
if *aborted.lock().unwrap() {
break;
+1 -1
View File
@@ -129,7 +129,7 @@ pub fn print_console_info(
log::warn!(
"{}",
format!(
"There were {} warning messages during the build.",
"There were {} warning messages during the build. Run `cargo check` to see them.",
options.warnings.len() - 1
)
.yellow()
+6 -3
View File
@@ -23,9 +23,12 @@
`dioxus-core-macro` provides a handful of helpful macros used by the `dioxus` crate. These include:
- The `rsx!` macro that underpins templates and node creation
- The `inline_props` macro transforms function arguments into an auto-derived struct
- The `format_args_f` macro which allows f-string formatting with support for expressions
- The `rsx!` macro that underpins templates and node creation.
- The `component` attribute macro denotes a function as a Dioxus component. Currently, this:
- Transforms function arguments into an auto-derived struct.
- Ensures that your component name uses PascalCase.
- Probably more stuff in the future. This macro allows us to have a way of distinguishing functions and components, which can be quite handy.
- The `format_args_f` macro which allows f-string formatting with support for expressions.
## Contributing
+1 -1
View File
@@ -128,7 +128,7 @@ impl ScopeContext {
parent.name
);
if let Some(shared) = parent.shared_contexts.borrow().iter().find_map(|any| {
tracing::trace!("found context {:?}", any.type_id());
tracing::trace!("found context {:?}", (**any).type_id());
any.downcast_ref::<T>()
}) {
return Some(shared.clone());
+1 -1
View File
@@ -36,7 +36,7 @@ fn suspended_child(cx: Scope) -> Element {
cx.spawn(async move {
val += 1;
});
return cx.suspend()?;
cx.suspend()?;
}
render!("child")
-1
View File
@@ -10,7 +10,6 @@ keywords = ["dom", "ui", "gui", "react", "terminal"]
license = "MIT OR Apache-2.0"
[dependencies]
dioxus = { workspace = true }
dioxus-core = { workspace = true, features = ["serialize"] }
dioxus-html = { workspace = true }
dioxus-native-core = { workspace = true, features = ["dioxus"] }
+23 -21
View File
@@ -1,7 +1,7 @@
#![cfg_attr(feature = "nightly-features", feature(debug_refcell))]
#[macro_export]
/// A helper macro for using hooks and properties in async environements.
/// A helper macro for using hooks and properties in async environments.
///
/// # Usage
///
@@ -54,35 +54,37 @@ macro_rules! to_owned {
pub mod computed;
mod use_on_unmount;
pub use use_on_unmount::*;
mod use_on_destroy;
pub use use_on_destroy::*;
mod usecontext;
pub use usecontext::*;
mod use_context;
pub use use_context::*;
mod usestate;
pub use usestate::{use_state, UseState};
mod use_state;
pub use use_state::{use_state, UseState};
mod useref;
pub use useref::*;
mod use_ref;
pub use use_ref::*;
mod use_shared_state;
pub use use_shared_state::*;
mod usecoroutine;
pub use usecoroutine::*;
mod use_coroutine;
pub use use_coroutine::*;
mod usefuture;
pub use usefuture::*;
mod use_future;
pub use use_future::*;
mod useeffect;
pub use useeffect::*;
mod use_effect;
pub use use_effect::*;
mod usecallback;
pub use usecallback::*;
mod use_callback;
pub use use_callback::*;
mod usememo;
pub use usememo::*;
mod use_memo;
pub use use_memo::*;
mod userootcontext;
pub use userootcontext::*;
mod use_on_create;
pub use use_on_create::*;
mod use_root_context;
pub use use_root_context::*;
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -3,13 +3,18 @@ use std::{any::Any, cell::Cell, future::Future};
use crate::UseFutureDep;
/// A hook that provides a future that executes after the hooks have been applied
/// A hook that provides a future that executes after the hooks have been applied.
///
/// Whenever the hooks dependencies change, the future will be re-evaluated.
/// If a future is pending when the dependencies change, the previous future
/// will be allowed to continue
/// will be allowed to continue.
///
/// - dependencies: a tuple of references to values that are `PartialEq` + `Clone`
/// **Note:** If your dependency list is always empty, use [`use_on_create`](crate::use_on_create).
///
/// ## Arguments
///
/// - `dependencies`: a tuple of references to values that are `PartialEq` + `Clone`.
/// - `future`: a closure that takes the `dependencies` as arguments and returns a `'static` future.
///
/// ## Examples
///
File renamed without changes.
File renamed without changes.
File renamed without changes.
+27
View File
@@ -0,0 +1,27 @@
use dioxus_core::ScopeState;
use std::cell::Cell;
use std::future::Future;
/// A hook that runs a future when the component is mounted.
///
/// This is just [`use_effect`](crate::use_effect), but with no dependencies.
/// If you have no dependencies, it's recommended to use this, not just because it's more readable,
/// but also because it's a tiny bit more efficient.
pub fn use_on_create<T, F>(cx: &ScopeState, future: impl FnOnce() -> F)
where
T: 'static,
F: Future<Output = T> + 'static,
{
let needs_regen = cx.use_hook(|| Cell::new(true));
if needs_regen.get() {
// We don't need regen anymore
needs_regen.set(false);
let fut = future();
cx.push_future(async move {
fut.await;
});
}
}
@@ -1,9 +1,20 @@
/// Creates a callback that will be run before the component is removed. This can be used to clean up side effects from the component (created with use_effect)
#[deprecated(
note = "Use `use_on_destroy` instead, which has the same functionality. \
This is deprecated because of the introduction of `use_on_create` which is better mirrored by `use_on_destroy`. \
The reason why `use_on_create` is not `use_on_mount` is because of potential confusion with `dioxus::events::onmounted`."
)]
pub fn use_on_unmount<D: FnOnce() + 'static>(cx: &dioxus_core::ScopeState, destroy: D) {
use_on_destroy(cx, destroy);
}
/// Creates a callback that will be run before the component is removed.
/// This can be used to clean up side effects from the component
/// (created with [`use_effect`](crate::use_effect)).
///
/// Example:
/// ```rust
/// use dioxus::prelude::*;
///
/// fn app(cx: Scope) -> Element {
/// let state = use_state(cx, || true);
/// render! {
@@ -25,7 +36,7 @@
/// }
/// }
/// }
///
/// fn child_component(cx: Scope) -> Element {
/// let original_scroll_position = use_state(cx, || 0.0);
/// use_effect(cx, (), move |_| {
@@ -38,8 +49,8 @@
/// original_scroll_position.set(window.scroll_y().unwrap());
/// }
/// });
/// use_on_unmount(cx, {
///
/// use_on_destroy(cx, {
/// to_owned![original_scroll_position];
/// /// restore scroll to the top of the page
/// move || {
@@ -47,7 +58,7 @@
/// window.scroll_with_x_and_y(*original_scroll_position.current(), 0.0);
/// }
/// });
///
/// render!{
/// div {
/// id: "my_element",
@@ -56,7 +67,7 @@
/// }
/// }
/// ```
pub fn use_on_unmount<D: FnOnce() + 'static>(cx: &dioxus_core::ScopeState, destroy: D) {
pub fn use_on_destroy<D: FnOnce() + 'static>(cx: &dioxus_core::ScopeState, destroy: D) {
cx.use_hook(|| LifeCycle {
ondestroy: Some(destroy),
});
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
View File
Whitespace-only changes.
+1
View File
@@ -1203,6 +1203,7 @@ builder_constructors! {
value: String DEFAULT,
selected: Bool volatile,
initial_selected: Bool DEFAULT,
};
/// Build a
+3
View File
@@ -54,6 +54,9 @@ export function setAttributeInner(node, field, value, ns) {
case "selected":
node.selected = truthy(value);
break;
case "initial_selected":
node.defaultSelected = truthy(value);
break;
case "dangerous_inner_html":
node.innerHTML = value;
break;
@@ -83,6 +83,9 @@ mod js {
case "selected":
node.selected = truthy(value);
break;
case "initial_selected":
node.defaultSelected = truthy(value);
break;
case "dangerous_inner_html":
node.innerHTML = value;
break;
+36 -25
View File
@@ -19,32 +19,43 @@ async fn main() {
let addr: std::net::SocketAddr = ([127, 0, 0, 1], 3030).into();
let view = dioxus_liveview::LiveViewPool::new();
let index_page_with_glue = |glue: &str| {
Html(format!(
r#"
<!DOCTYPE html>
<html>
<head> <title>Dioxus LiveView with axum</title> </head>
<body> <div id="main"></div> </body>
{glue}
</html>
"#,
))
};
let app = Router::new()
.route(
"/",
get(move || async move {
Html(format!(
r#"
<!DOCTYPE html>
<html>
<head> <title>Dioxus LiveView with axum</title> </head>
<body> <div id="main"></div> </body>
{glue}
</html>
"#,
glue = dioxus_liveview::interpreter_glue(&format!("ws://{addr}/ws"))
))
}),
)
.route(
"/ws",
get(move |ws: WebSocketUpgrade| async move {
ws.on_upgrade(move |socket| async move {
_ = view.launch(dioxus_liveview::axum_socket(socket), app).await;
})
}),
);
let app =
Router::new()
.route(
"/",
get(move || async move {
index_page_with_glue(&dioxus_liveview::interpreter_glue(&format!(
"ws://{addr}/ws"
)))
}),
)
.route(
"/as-path",
get(move || async move {
index_page_with_glue(&dioxus_liveview::interpreter_glue("/ws"))
}),
)
.route(
"/ws",
get(move |ws: WebSocketUpgrade| async move {
ws.on_upgrade(move |socket| async move {
_ = view.launch(dioxus_liveview::axum_socket(socket), app).await;
})
}),
);
println!("Listening on http://{addr}");
+38 -3
View File
@@ -93,14 +93,49 @@ static MAIN_JS: &str = include_str!("./main.js");
/// This script that gets injected into your app connects this page to the websocket endpoint
///
/// Once the endpoint is connected, it will send the initial state of the app, and then start
/// processing user events and returning edits to the liveview instance
pub fn interpreter_glue(url: &str) -> String {
/// processing user events and returning edits to the liveview instance.
///
/// You can pass a relative path prefixed with "/", or enter a full URL including the protocol
/// (`ws:` or `wss:`) as an argument.
///
/// If you enter a relative path, the web client automatically prefixes the host address in
/// `window.location` when creating a web socket to LiveView.
///
/// ```
/// // Creates websocket connection to same host as current page
/// interpreter_glue("/api/liveview");
///
/// // Creates websocket connection to specified url
/// interpreter_glue("ws://localhost:8080/api/liveview");
/// ```
pub fn interpreter_glue(url_or_path: &str) -> String {
// If the url starts with a `/`, generate glue which reuses current host
let get_ws_url = if url_or_path.starts_with('/') {
r#"
let loc = window.location;
let new_url = "";
if (loc.protocol === "https:") {{
new_url = "wss:";
}} else {{
new_url = "ws:";
}}
new_url += "//" + loc.host + path;
return new_url;
"#
} else {
"return path;"
};
let js = &*INTERPRETER_JS;
let common = &*COMMON_JS;
format!(
r#"
<script>
var WS_ADDR = "{url}";
function __dioxusGetWsUrl(path) {{
{get_ws_url}
}}
var WS_ADDR = __dioxusGetWsUrl("{url_or_path}");
{js}
{common}
{MAIN_JS}
-2
View File
@@ -16,7 +16,6 @@ keyboard-types = "0.7"
smallvec = "1.6"
rustc-hash = { workspace = true }
anymap = "1.0.0-beta.2"
slab = { workspace = true }
parking_lot = { version = "0.12.1", features = ["send_guard"] }
dashmap = "5.4.0"
@@ -24,7 +23,6 @@ dashmap = "5.4.0"
taffy = { version = "0.3.12", optional = true }
lightningcss = { version = "1.0.0-alpha.39", optional = true }
rayon = "1.6.1"
shipyard = { version = "0.6.2", features = ["proc", "std"], default-features = false }
[dev-dependencies]