Feat: more docs, example, mroe nodes

This commit is contained in:
Jonathan Kelley 2021-01-15 23:25:29 -05:00
parent 152bced9f3
commit d13e04c9ff
14 changed files with 303 additions and 34 deletions

View file

@ -1 +1,3 @@
bearly bearly
Clippy
tide_ssr

View file

@ -1,6 +1,39 @@
# Initial Release # Project: Live-View
# Project: Sanitization (TBD)
- [ ] (Macro) Clippy sanity for html macro
- [ ] (Macro) Error sanitization
# Project: Examples
> Get *all* the examples
- [ ] (Examples) Tide example with templating
# Project: State management
> Get some global state management installed with the hooks API
# Project: Hooks + Context + Subscriptions (TBD)
> Implement a light-weight string renderer with basic caching
- [ ] Implement context object
# Project: Concurrency (TBD)
> Ensure the concurrency model works well, play with lifetimes to check if it can be multithreaded + halted
# Project: Web_sys renderer (TBD)
- [ ] (Web) Web-sys renderer and web tests
# Project: String Render (TBD)
> Implement a light-weight string renderer with basic caching
- [ ] (SSR) Implement stateful 3rd party string renderer
- [ ] (Macro) Make VText nodes automatically capture and format IE allow "Text is {blah}" in place of {format!("Text is {}",blah)}
# Project: Initial Release (TBD)
> Get the initial VDom + Event System + Patching + Diffing + Component framework up and running
- [x] (Core) Migrate virtual node into new VNode type
- [ ] (Core) Arena allocate VNodes
- [ ] (Core) Allow VNodes to borrow arena contents
- [ ] (Macro) Tweak event syntax to not be dependent on wasm32 target (just return regular closures) - [ ] (Macro) Tweak event syntax to not be dependent on wasm32 target (just return regular closures)
- [ ] (Macro) Tweak component syntax to accept a new custom element - [ ] (Macro) Tweak component syntax to accept a new custom element
- [ ] (Core) Introduce the VDOM and patch API for 3rd party renderers - [ ] (Core) Introduce the VDOM and patch API for 3rd party renderers
- [ ] (Web) Web-sys renderer and web tests
- [ ] (Examples) Tide example with templating

View file

@ -15,4 +15,5 @@ members = [
"packages/html-macro-test", "packages/html-macro-test",
"packages/virtual-dom-rs", "packages/virtual-dom-rs",
"packages/virtual-node", "packages/virtual-node",
"examples",
] ]

View file

@ -30,7 +30,7 @@ fn Example(ctx: &Context<{ name: String }>) -> VNode {
static Example: FC<{ name: String }> = |ctx| html! { <div> "Hello {:?name}!" </div> }; static Example: FC<{ name: String }> = |ctx| html! { <div> "Hello {:?name}!" </div> };
``` ```
The final output of components must be a tree of VNodes. We provide an html macro for using JSX-style syntax to write these, though, you could use any macro, dsl, or templating engine. Work is being done on a terra template processor for existing templates. The final output of components must be a tree of VNodes. We provide an html macro for using JSX-style syntax to write these, though, you could use any macro, DSL, or templating engine. Work is being done on a terra template processor for existing templates.
## Features ## Features
@ -58,32 +58,11 @@ async fn user_data(ctx: &Context<()>) -> VNode {
Asynchronous components are powerful but can also be easy to misuse as they pause rendering for the component and its children. Refer to the concurrent guide for information on how to best use async components. Asynchronous components are powerful but can also be easy to misuse as they pause rendering for the component and its children. Refer to the concurrent guide for information on how to best use async components.
## Example ## Examples
- Isomorphic: serve a server-rendered webapp using Tide We use `diopack` to build and test apps. This can run examples, tests, build web workers, launch development servers, bundle, and more. It's general purpose, but currently very tailored to Dioxus for liveview and bundling. Alternatively, `Trunk` works but can't run examples.
- tide_ssr: Handle an HTTP request and return an html body using the html! macro.
## Documentation ## Documentation
| Chapter | Description | We have a pretty robust
| -------------- | ------------------------------------------ |
| 1-hello-world | Intro to Dioxus |
| 2-utilities | Tools to make writing apps easier |
| 3-hello-world | Html + functional_component macro |
| 4-hello-world | Renderer + event integration using web_sys |
| 5-hello-world | Virtual DOM, patching/diffing |
| 6-hello-world | Standard bundle of useful hooks |
| 7-hello-world | Html + functional_component macro |
| 8-hello-world | Renderer + event integration using web_sys |
| 9-hello-world | Renderer + event integration using web_sys |
| 10-hello-world | Renderer + event integration using web_sys |
## Packages
| Package | Use |
| --------- | ------------------------------------------ |
| core | Virtual DOM, patching/diffing |
| hooks | Standard bundle of useful hooks |
| macro | Html + functional_component macro |
| web | Renderer + event integration using web_sys |
| live-view | Dedicated isomorphic framework |
| recoil | Data-flow-graph state management |
| redux | Reducer-style state management |
| bearly | Simple and idiomatic state management |

32
docs/0-index.md Normal file
View file

@ -0,0 +1,32 @@
# Dioxus Chapter 0 - Intro + Index
## Guides
------------------
| Chapter | Description |
| -------------- | ------------------------------------------ |
| 1-hello-world | Intro to Dioxus |
| 2-utilities | Tools to make writing apps easier |
| 3-hello-world | Html + functional_component macro |
| 4-hello-world | Renderer + event integration using web_sys |
| 5-hello-world | Virtual DOM, patching/diffing |
| 6-hello-world | Standard bundle of useful hooks |
| 7-hello-world | Html + functional_component macro |
| 8-hello-world | Renderer + event integration using web_sys |
| 9-hello-world | Renderer + event integration using web_sys |
| 10-hello-world | Renderer + event integration using web_sys |
## Development
------------------
| Package | Use |
| ------- | ------------------------------------------------ |
| full | Batteries-included entrypoint with feature flags |
| core | Virtual DOM, diffing, patching, and events |
| hooks | Standard hooks |
| macro | Html + functional_component macro |
| web | Renderer + event integration using web_sys |
| live | Dedicated isomorphic framework |
| recoil | Data-flow-graph state management |
| redux | Reducer-style state management |
| bearly | Simple and idiomatic state management |

30
examples/Cargo.toml Normal file
View file

@ -0,0 +1,30 @@
[package]
name = "dioxus-examples"
version = "0.0.0"
authors = ["Jonathan Kelley <jkelleyrtp@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
fern = { vesion = "0.6.0", features = ["colored"] }
log = "0.4.13"
dioxus-core = { path = "../packages/core" }
rand = "0.8.2"
[dev-dependencies]
async-std = { version = "1.9.0", features = ["attributes"] }
tide = { version = "0.15.0" }
[lib]
path = "common.rs"
[[example]]
path = "hello.rs"
name = "hello"
[[example]]
path = "tide_ssr.rs"
name = "tide_ssr"

52
examples/common.rs Normal file
View file

@ -0,0 +1,52 @@
//! Common utilities for integration examples
pub mod logger {
use fern::colors::{Color, ColoredLevelConfig};
use log::debug;
pub fn set_up_logging(bin_name: &'static str) {
// configure colors for the whole line
let colors_line = ColoredLevelConfig::new()
.error(Color::Red)
.warn(Color::Yellow)
// we actually don't need to specify the color for debug and info, they are white by default
.info(Color::White)
.debug(Color::White)
// depending on the terminals color scheme, this is the same as the background color
.trace(Color::BrightBlack);
// configure colors for the name of the level.
// since almost all of them are the same as the color for the whole line, we
// just clone `colors_line` and overwrite our changes
let colors_level = colors_line.clone().info(Color::Green);
// here we set up our fern Dispatch
fern::Dispatch::new()
.format(move |out, message, record| {
out.finish(format_args!(
"{color_line}[{level}{color_line}] {message}\x1B[0m",
color_line = format_args!(
"\x1B[{}m",
colors_line.get_color(&record.level()).to_fg_str()
),
level = colors_level.color(record.level()),
message = message,
));
})
// set the default log level. to filter out verbose log messages from dependencies, set
// this to Warn and overwrite the log level for your crate.
.level(log::LevelFilter::Warn)
// change log levels for individual modules. Note: This looks for the record's target
// field which defaults to the module path but can be overwritten with the `target`
// parameter:
// `info!(target="special_target", "This log message is about special_target");`
.level_for(bin_name, log::LevelFilter::Info)
// .level_for("pretty_colored", log::LevelFilter::Trace)
// output to stdout
.chain(std::io::stdout())
.apply()
.unwrap();
debug!("finished setting up logging! yay!");
}
}

9
examples/hello.rs Normal file
View file

@ -0,0 +1,9 @@
fn main() {
println!("Hello world!");
println!("Hello world!");
println!("Hello world!");
println!("Hello world!");
println!("Hello world!");
println!("Hello world!");
println!("Hello world!");
}

99
examples/tide_ssr.rs Normal file
View file

@ -0,0 +1,99 @@
//! This demo shows how to use the to_string utility on VNodes to convert them into valid HTML.
//! You can use the html! macro to craft webpages generated by the server on-the-fly.
//!
//! Server-side-renderered webpages are a great use of Rust's async story, where servers can handle
//! thousands of simultaneous clients on minimal hardware.
use dioxus_core::prelude::*;
use tide::{Request, Response};
#[async_std::main]
async fn main() -> Result<(), std::io::Error> {
dioxus_examples::logger::set_up_logging("tide_ssr");
// Build the API
let mut app = tide::new();
app.at("/fib/:n").get(fibsum);
// Launch the server
let addr = "127.0.0.1:8080";
log::info!("App is ready at {}", addr);
log::info!("Navigate to an fibonacci number, like so http://localhost:8080/fib/21");
app.listen(addr).await?;
Ok(())
}
/// Calculate the fibonacci number for a given request input
async fn fibsum(req: Request<()>) -> tide::Result<tide::Response> {
use std::time::Instant;
let n: usize = req.param("n")?.parse().unwrap_or(0);
fn fib(n: usize) -> usize {
if n == 0 || n == 1 {
n
} else {
fib(n - 1) + fib(n - 2)
}
}
// Start a stopwatch
// Compute the nth number in the fibonacci sequence
// Stop the stopwatch
let start = Instant::now();
let fib_n = fib(n);
let duration = start.elapsed().as_nanos();
let mut rng = rand::thread_rng();
use rand::Rng;
let other_fib_to_try = rng.gen_range(1..42);
let nodes = html! {
<html>
<head>
<meta content="text/html;charset=utf-8" />
<meta charset="UTF-8" />
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet" />
</head>
<body>
<div class="flex items-center justify-center flex-col">
<div class="flex items-center justify-center">
<div class="flex flex-col bg-white rounded p-4 w-full max-w-xs">
// Title
<div class="font-bold text-xl">
{format!("Fibonacci Calculator: n = {}",n)}
</div>
// Subtext / description
<div class="text-sm text-gray-500">
{format!("Calculated in {} nanoseconds",duration)}
</div>
<div class="flex flex-row items-center justify-center mt-6">
// Main number
<div class="font-medium text-6xl">
{format!("{}",fib_n)}
</div>
</div>
<div class="flex flex-row justify-between mt-6">
<a href=format!("http://localhost:8080/fib/{}", other_fib_to_try) class="underline">
{"Click to try another number"}
</a>
</div>
</div>
</div>
</div>
</body>
</html>
};
Ok(Response::builder(203)
.body(nodes.to_string())
.header("custom-header", "value")
.content_type(tide::http::mime::HTML)
.build())
}

View file

@ -8,10 +8,12 @@ edition = "2018"
[dependencies] [dependencies]
generational-arena = "0.2.8" generational-arena = "0.2.8"
typed-arena = "2.0.1"
virtual-dom-rs = { path = "../virtual-dom-rs" }
virtual-node = { path = "../virtual-node" }
html-macro = { path = "../html-macro" } html-macro = { path = "../html-macro" }
once_cell = "1.5.2" once_cell = "1.5.2"
# web-sys = "0.3.46" # web-sys = "0.3.46"
# js-sys = "0.3.46" # js-sys = "0.3.46"
# typed-arena = "2.0.1"
# virtual-dom-rs = { path = "../virtual-dom-rs" }
# virtual-node = { path = "../virtual-node" }

View file

@ -1,7 +1,7 @@
use std::future::Future; use std::future::Future;
use dioxus_core::{component::AnyContext, prelude::*}; use dioxus_core::{component::AnyContext, prelude::*};
use virtual_dom_rs::Closure; // use virtual_dom_rs::Closure;
// Stop-gap while developing // Stop-gap while developing
// Need to update the macro // Need to update the macro
@ -27,9 +27,18 @@ fn root(ctx: &mut AnyContext) -> VNode {
// or a manually crated vnode // or a manually crated vnode
{ {
let mut node_0 = VNode::element("div"); let mut node_0 = VNode::element("div");
{
if let Some(ref mut element_node) = node_0.as_velement_mut() {
// element_node.attrs.insert("blah", "blah");
// element_node.children.extend(node_0.into_iter());
}
}
let mut node_1: IterableNodes = ("Hello world!").into(); let mut node_1: IterableNodes = ("Hello world!").into();
node_1.first().insert_space_before_text(); node_1.first().insert_space_before_text();
let mut node_2 = VNode::element("button"); let mut node_2 = VNode::element("button");
let node_3 = VNode::Component(VComponent {});
{ {
// let closure = Closure::wrap(Box::new(|_| {}) as Box<FnMut(_)>); // let closure = Closure::wrap(Box::new(|_| {}) as Box<FnMut(_)>);
// let closure_rc = std::rc::Rc::new(closure); // let closure_rc = std::rc::Rc::new(closure);

View file

@ -25,6 +25,9 @@ pub mod prelude {
pub use nodes::iterables::IterableNodes; pub use nodes::iterables::IterableNodes;
pub use nodes::*; pub use nodes::*;
// hack "virtualnode"
pub type VirtualNode = VNode;
// Re-export from the macro crate // Re-export from the macro crate
pub use html_macro::html; pub use html_macro::html;
} }
@ -262,6 +265,8 @@ pub mod nodes {
/// HTML attributes such as id, class, style, etc /// HTML attributes such as id, class, style, etc
pub attrs: HashMap<String, String>, pub attrs: HashMap<String, String>,
// TODO: @JON Get this to not heap allocate, but rather borrow
// pub attrs: HashMap<&'static str, &'static str>,
// TODO @Jon, re-enable "events" // TODO @Jon, re-enable "events"
// //

9
packages/ssr/Cargo.toml Normal file
View file

@ -0,0 +1,9 @@
[package]
name = "dioxus-ssr"
version = "0.0.0"
authors = ["Jonathan Kelley <jkelleyrtp@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

7
packages/ssr/src/lib.rs Normal file
View file

@ -0,0 +1,7 @@
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}