瀏覽代碼

Merge pull request #6 from jkelleyrtp/jk/diff_machine_own_vdom

wip: new approach at direct access to vdom
Jonathan Kelley 4 年之前
父節點
當前提交
984828f399
共有 61 個文件被更改,包括 1157 次插入2741 次删除
  1. 2 0
      .vscode/spellright.dict
  2. 3 3
      Cargo.toml
  3. 4 6
      README.md
  4. 二進制
      docs/assets/01-setup-helloworld.png
  5. 3 0
      docs/main-concepts/00-index.md
  6. 57 0
      docs/main-concepts/01-setup.md
  7. 142 0
      docs/main-concepts/02-hello.md
  8. 156 0
      docs/main-concepts/03-rsx.md
  9. 29 0
      docs/main-concepts/testing.md
  10. 3 0
      docs/platforms/00-index.md
  11. 0 0
      docs/platforms/01-ssr.md
  12. 0 0
      docs/platforms/02-wasm.md
  13. 0 0
      docs/platforms/03-desktop.md
  14. 0 0
      docs/platforms/04-concurrency.md
  15. 0 0
      docs/platforms/05-liveview.md
  16. 0 0
      docs/platforms/06-components.md
  17. 二進制
      docs/rocketsrchrome_files/cloud-0.png
  18. 二進制
      docs/rocketsrchrome_files/cloud-1.png
  19. 二進制
      docs/rocketsrchrome_files/cloud-2.png
  20. 0 1
      docs/rocketsrchrome_files/config-icon.svg
  21. 0 1
      docs/rocketsrchrome_files/cookies-icon.svg
  22. 0 32
      docs/rocketsrchrome_files/css
  23. 0 1
      docs/rocketsrchrome_files/helmet.svg
  24. 0 1
      docs/rocketsrchrome_files/logo-small.svg
  25. 0 1
      docs/rocketsrchrome_files/robot-free.svg
  26. 0 1
      docs/rocketsrchrome_files/ship-icon.svg
  27. 0 1
      docs/rocketsrchrome_files/streams-icon.svg
  28. 0 2033
      docs/rocketsrchrome_files/style.css
  29. 0 1
      docs/rocketsrchrome_files/sun.svg
  30. 0 1
      docs/rocketsrchrome_files/telescope.svg
  31. 0 1
      docs/rocketsrchrome_files/templating-icon.svg
  32. 0 1
      docs/rocketsrchrome_files/testing-icon.svg
  33. 35 35
      notes/Parity.md
  34. 2 1
      packages/core-macro/examples/prop_test.rs
  35. 2 1
      packages/core-macro/src/props/mod.rs
  36. 5 6
      packages/core-macro/src/rsx/ambiguous.rs
  37. 25 11
      packages/core-macro/src/rsx/component.rs
  38. 20 8
      packages/core-macro/src/rsx/element.rs
  39. 36 3
      packages/core-macro/src/rsx/fragment.rs
  40. 39 28
      packages/core-macro/src/rsx/mod.rs
  41. 1 1
      packages/core/.vscode/settings.json
  42. 1 0
      packages/core/examples/borrowed.rs
  43. 2 0
      packages/core/examples/nested.rs
  44. 27 2
      packages/core/src/arena.rs
  45. 12 117
      packages/core/src/component.rs
  46. 198 112
      packages/core/src/diff.rs
  47. 2 14
      packages/core/src/lib.rs
  48. 59 8
      packages/core/src/nodebuilder.rs
  49. 107 69
      packages/core/src/nodes.rs
  50. 2 0
      packages/core/src/patch.rs
  51. 65 211
      packages/core/src/virtual_dom.rs
  52. 1 1
      packages/hooks/src/lib.rs
  53. 1 1
      packages/recoil/examples/callback.rs
  54. 15 18
      packages/recoil/src/lib.rs
  55. 36 0
      packages/web/examples/children.rs
  56. 1 1
      packages/web/examples/context.rs
  57. 25 0
      packages/web/examples/fragment.rs
  58. 11 0
      packages/web/examples/helloworld.rs
  59. 21 0
      packages/web/examples/many.rs
  60. 2 2
      packages/web/examples/rsxt.rs
  61. 5 6
      packages/web/examples/todomvcsingle.rs

+ 2 - 0
.vscode/spellright.dict

@@ -46,3 +46,5 @@ impl
 destructured
 linting
 lodash
+crates.io
+utilties

+ 3 - 3
Cargo.toml

@@ -5,11 +5,11 @@ members = [
     "packages/core",
     "packages/web",
     "packages/dioxus",
-    "packages/recoil",
-    "packages/docsite",
     "packages/ssr",
-    "packages/webview",
 ]
+# "packages/recoil",
+# "packages/docsite",
+# "packages/webview",
 
 # "packages/cli",
 # "packages/webview",

+ 4 - 6
README.md

@@ -8,15 +8,13 @@
 Dioxus is a portable, performant, and ergonomic framework for building cross-platform user experiences in Rust.
 
 ```rust
-fn Example(ctx: Context<()>) -> VNode {
+fn Example(ctx: Context<()>) -> VNodes {
     let (selection, set_selection) = use_state(&ctx, move || "..?");
 
     ctx.render(rsx! {
-        div {
-            h1 { "Hello, {selection}" }
-            button { "?", onclick: move |_| set_selection("world!")}
-            button { "?", onclick: move |_| set_selection("Dioxus 🎉")}
-        }
+        h1 { "Hello, {selection}" }
+        button { "?", onclick: move |_| set_selection("world!")}
+        button { "?", onclick: move |_| set_selection("Dioxus 🎉")}
     })
 };
 ```

二進制
docs/assets/01-setup-helloworld.png


+ 3 - 0
docs/main-concepts/00-index.md

@@ -0,0 +1,3 @@
+# Getting Started
+
+This page is an overview of the Dioxus documentation.

+ 57 - 0
docs/main-concepts/01-setup.md

@@ -0,0 +1,57 @@
+# Overview
+
+Dioxus aims to provide a fast, friendly, and portable toolkit for building user interfaces with Rust.
+
+This guide assumes you'll be building a SPA (single page application) for the web. The process for building desktop apps, server-rendered apps, static sites, and mobile apps, is more-or-less the same. You can check out the [Platform Specific Guides](../platforms/00-index.md) for more information on setting up Dioxus for any of the various targets you are building for.
+
+# Setting up Dioxus
+
+Dioxus requires a few main things to get up and running:
+
+- The [Rust compiler](https://www.rust-lang.org) and associated build tooling
+
+- An editor of your choice, with the [Rust-Analyzer LSP plugin](https://rust-analyzer.github.io)
+
+Dioxus integrates very well with the Rust-Analyzer IDE plugin which will provide appropriate syntax highlighting, code navigation, folding, and more.
+
+We also recommend installing the Dioxus CLI. The Dioxus CLI automates building and packaging for various targets and integrates with simulators, development servers, and app deployment. It'll be our one-stop-shop for anything related to building and sharing our Dioxus Apps. To install the CLI, you'll need cargo (should be automatically installed with Rust):
+
+```
+$ cargo install dioxus-cli
+```
+
+You can update the dioxus-cli at any time with:
+
+```
+$ cargo install --force dioxus-cli
+```
+
+If your version of the CLI is out of date, it'll remind you to update whenever a new version is uploaded to Rust's package manager [crates.io](https://crates.io). We use a dedicated 1st-party CLI to save you from having to run potentially untrusted code every time you add a crate to your project - as is standard in the NPM ecosystem. You can vet the source of the Dioxus-CLI yourself at its [GitHub repo](https://github.com/jkelleyrtp/dioxus/tree/master/packages/cli).
+
+If you want to keep your traditional `npm install XXX` workflow for adding packages, you might want to install `cargo-edit` and a few other fun `cargo` extensions:
+
+- [cargo edit](https://github.com/killercup/cargo-edit) for adding dependencies from the CLI
+- [cargo-expand](https://github.com/dtolnay/cargo-expand) for expanding macro calls
+- `cargo tree` - an integrated cargo command that lets you inspect your dependency tree
+
+That's it! We won't need to touch NPM/WebPack/Babel/Parcel, etc.
+
+# Important tools
+
+With Rust, things like benchmarking, testing, and documentation are included in the language. We strongly recommend going through the official Rust book _completely_. However, our hope is that a Dioxus app can serve as a great first project. With Dioxus you'll learn about:
+
+- Error handling
+- Structs, Functions, Enums
+- Closures
+- Macros
+
+We've put a lot of care into making Dioxus syntax familiar and easy to understand, so you won't need knowledge on async, lifetimes, and smart pointers until you really start building complex Dioxus apps.
+
+We strongly encourage exploring the guides for more information on how to work with the integrated tooling:
+
+- [Testing](Testing.md)
+- [Documentation](Documentation.md)
+- [Benchmarking](Benchmarking.md)
+- [Building](Building.md)
+- [Modules](Modules.md)
+- [Crates](Crates.md)

+ 142 - 0
docs/main-concepts/02-hello.md

@@ -0,0 +1,142 @@
+# Hello World
+
+Let's put together a simple "hello world" to get acquainted with Dioxus. The Dioxus-CLI has an equivalent to "create-react-app" built-in, but setting up Dioxus apps is simple enough to not need additional tooling.
+
+First, let's start a new project. Rust has the concept of executables and libraries. Executables have a `main.rs` and libraries have `lib.rs`. A project may have both. Our `hello world` will be an executable - we expect our app to launch when we run it! Cargo provides this for us:
+
+```shell
+$ cargo new --bin hello-dioxus
+```
+
+Now, we can `cd` into our project and poke around:
+
+```shell
+$ cd hello-dioxus
+$ tree
+.
+├── Cargo.toml
+├── .git
+├── .gitignore
+└── src
+    └── main.rs
+```
+
+We are greeted with a pre-initialized git repository, our code folder (`src`) and our project file (`Cargo.toml`).
+
+Our `src` folder holds our code. Our `main.rs` file holds our `fn main` which will be executed when our app is ran.
+
+```shell
+$ more src/main.rs
+```
+
+```rust
+fn main() {
+    println!("Hello, world!");
+}
+```
+
+Right now, whenever our app is launched, "Hello world" will be echoed to the terminal.
+
+```shell
+$ cargo run
+   Compiling hello-dioxus v0.1.0
+    Finished dev [unoptimized + debuginfo] target(s) in 0.41s
+     Running `target/debug/hello-dioxus`
+Hello, world!
+```
+
+Our `Cargo.toml` file holds our dependencies and project flags.
+
+```shell
+$ cat Cargo.toml
+```
+
+```toml
+[package]
+name = "hello-dioxus"
+version = "0.1.0"
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+
+```
+
+To use the Dioxus library, we'll want to add the most recent version of `Dioxus` to our crate. If you have `cargo edit` installed, simply call:
+
+```shell
+$ cargo add dioxus --features web
+```
+
+It's very important to add `dioxus` with the `web` feature for this example. The `dioxus` crate is a batteries-include crate that combines a bunch of utility crates together, ensuring compatibility of the most important parts of the ecosystem. Under the hood, the `dioxus` crate configures various renderers, hooks, debug tooling, and more. The `web` feature ensures the we only depend on the smallest set of required crates to compile.
+
+If you plan to develop extensions for the `Dioxus` ecosystem, please use `dioxus-core` crate. The `dioxus` crate re-exports `dioxus-core` alongside other utilties. As a result, `dioxus-core` is much more stable than the batteries-included `dioxus` crate.
+
+Now, let's edit our `main.rs` file:
+
+```rust
+use diouxs::prelude::*;
+
+fn main() {
+    dioxus::web::start(App)
+}
+
+fn App(ctx: Context<()>) -> VNode {
+    ctx.render(rsx! {
+        div { "Hello, world!" }
+    })
+}
+```
+
+Let's dissect our example a bit.
+
+This bit of code imports everything from the the `prelude` module. This brings into scope the right traits, types, and macros needed for working with Dioxus.
+
+```rust
+use diouxs::prelude::*;
+```
+
+This bit of code starts the WASM renderer as a future (JS Promise) and then awaits it. This is very similar to the `ReactDOM.render()` method you use for a React app. We pass in the `App` function as a our app.
+
+```rust
+fn main() {
+    dioxus::web::start(App)
+}
+```
+
+Finally, our app. Every component in Dioxus is a function that takes in a `Context` object and returns a `VNode`.
+
+```rust
+fn App(ctx: Context<()>) -> VNode {
+    ctx.render(rsx! {
+        div { "Hello, world!" }
+    })
+};
+```
+
+In React, you'll save data between renders with hooks. However, hooks rely on global variables which make them difficult to integrate in multi-tenant systems like server-rendering. In Dioxus, you are given an explicit `Context` object to control how the component renders and stores data.
+
+Next, we're greeted with the `rsx!` macro. This lets us add a custom DSL for declaratively building the structure of our app. The semantics of this macro are similar to that of JSX and HTML, though with a familiar Rust-y interface. The `html!` macro is also available for writing components with a JSX/HTML syntax.
+
+The `rsx!` macro is lazy: it does not immediately produce elements or allocates, but rather builds a closure which can be rendered with `ctx.render`.
+
+Now, let's launch our app in a development server:
+
+```shell
+$ dioxus develop
+```
+
+Huzzah! We have a simple app.
+
+![Hello world](../assets/01-setup-helloworld.png)
+
+If we wanted to golf a bit, we can shrink our hello-world even smaller:
+
+```rust
+fn main() {
+    dioxus::web::start(|ctx| ctx.render(diouxs::rsx!( div { "Hello, World!" } ))
+}
+```
+
+Anyways, let's move on to something a bit more complex.

+ 156 - 0
docs/main-concepts/03-rsx.md

@@ -0,0 +1,156 @@
+# VNode Macros
+
+Dioxus comes preloaded with two macros for creating VNodes.
+
+## html! macro
+
+The html! macro supports a limited subset of the html standard. This macro will happily accept a copy-paste from something like tailwind builder. However, writing HTML by hand is a bit tedious - IDE tools for Rust don't support linting/autocomplete/syntax highlighting. RSX is much more natural for Rust programs and _does_ integrate well with Rust IDE tools.
+
+There is also limited support for dynamic handlers, but it will function similarly to JSX.
+
+You'll want to write RSX where you can, and in a future release we'll have a tool that automatically converts HTML to RSX.
+
+```rust
+#[fc]
+fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
+    ctx.render(html! {
+        <div>
+            <p> "Hello, {name}!" </p>
+            <p> "Status: {pending}!" </p>
+            <p> "Count {count}!" </p>
+        </div>
+    })
+}
+```
+
+## rsx! macro
+
+The rsx! macro is a VNode builder macro designed especially for Rust programs. Writing these should feel very natural, much like assembling a struct. VSCode also supports these with code folding, bracket-tabbing, bracket highlighting, and section selecting.
+
+The Dioxus VSCode extension will eventually provide a macro to convert a selection of html! template and turn it into rsx!, so you'll never need to transcribe templates by hand.
+
+It's also a bit easier on the eyes 🙂.
+
+```rust
+#[fc]
+fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
+    ctx.render(rsx! {
+        div {
+            p {"Hello, {name}!"}
+            p {"Status: {pending}!"}
+            p {"Count {count}!"}
+        }
+    })
+}
+
+```
+
+Each element takes a comma-separated list of expressions to build the node. Roughly, here's how they work:
+
+- `name: value` sets the property on this element.
+- `"text"` adds a new text element
+- `tag {}` adds a new child element
+- `CustomTag {}` adds a new child component
+- `{expr}` pastes the `expr` tokens literally. They must be IntoCtx<Vnode> to work properly
+
+Commas are entirely optional, but might be useful to delineate between elements and attributes.
+
+The `render` function provides an **extremely efficient** allocator for VNodes and text, so try not to use the `format!` macro in your components. Rust's default `ToString` methods pass through the global allocator, but all text in components is allocated inside a manually-managed Bump arena.
+
+```rust
+static Example: FC<()> = |ctx| {
+
+    let text = "example";
+
+    let g = async {
+        wait(10).await;
+        "hello"
+    };
+
+    let user_name = use_read_async(ctx, USERNAME);
+    let title = ctx.suspend(user_name, |user_name| rsx!{ h1 { "Welcome back, {user_name}" } });
+
+
+    ctx.render(rsx!{
+        div {
+            h1 { "Example" },
+
+            {title}
+
+            // fstring interpolation
+            "{text}"
+
+            p {
+                // Attributes
+                tag: "type",
+
+                // Anything that implements display can be an attribute
+                abc: 123,
+                enabled: true,
+
+                // attributes also supports interpolation
+                // `class` is not a restricted keyword unlike JS and ClassName
+                class: "big small wide short {text}",
+
+                // bool-based classnames
+                classes: [("big", true), ("small", false)]
+
+                // Bool-based props
+                // *must* be in the tuple form, cannot enter as a variable
+                tag: ("type", false)
+
+                tag: {"these tokens are placed directly"}
+
+                // Children
+                a { "abcder" },
+
+                // Children with attributes
+                h2 { "hello", class: "abc-123" },
+
+                // Child components
+                CustomComponent { a: 123, b: 456, key: "1" },
+
+                // Child components with paths
+                crate::components::CustomComponent { a: 123, b: 456, key: "1" },
+
+                // Iterators
+                { 0..3.map(|i| rsx!( h1 {"{:i}"} )) },
+
+                // More rsx!, or even html!
+                { rsx! { div { } } },
+                { html! { <div> </div> } },
+
+                // Matching
+                // Requires rendering the nodes first.
+                // rsx! is lazy, and the underlying closures cannot have the same type
+                // Rendering produces the VNode type
+                {match rand::gen_range::<i32>(1..3) {
+                    1 => rsx!(in ctx, h1 { "big" })
+                    2 => rsx!(in ctx, h2 { "medium" })
+                    _ => rsx!(in ctx, h3 { "small" })
+                }}
+
+                // Optionals
+                {true.and_then(|f| rsx!{ h1 {"Conditional Rendering"} })}
+
+                // Bool options
+                {(rsx!{ h1 {"Conditional Rendering"}, true)}
+
+                // Child nodes
+                // Returns &[VNode]
+                {ctx.children()}
+
+                // Duplicating nodes
+                // Clones the nodes by reference, so they are literally identical
+                {{
+                    let node = rsx!(in ctx, h1{ "TopNode" });
+                    (0..10).map(|_| node.clone())
+                }}
+
+                // Any expression that is `IntoVNode`
+                {expr}
+            }
+        }
+    })
+}
+```

+ 29 - 0
docs/main-concepts/testing.md

@@ -0,0 +1,29 @@
+## Testing
+
+To test your Rust code, you can annotate any function with the `#[test]` block. In VSCode with RA, this will provide a lens to click and run the test.
+
+```rust
+#[test]
+fn component_runs() {
+    assert!(true)
+}
+```
+
+This will test your Rust code _without_ going through the browser. This is ideal for squashing logic bugs and ensuring components render appropriately when the browsers's DOM is not needed. If you need to run tests in the browser, you can annotate your blocks with the `#[dioxus::test]` block.
+
+```rust
+#[dioxus::test]
+fn runs_in_browser() {
+    // ...
+}
+```
+
+Then, when you run
+
+```
+$ dioxus test --chrome
+```
+
+Dioxus will build and test your code using the Chrome browser as a harness.
+
+There's a lot more to testing if you dive in, so check out the [Testing]() guide for more information

+ 3 - 0
docs/guides/00-index.md → docs/platforms/00-index.md

@@ -1,4 +1,7 @@
+# Welcome to Dioxus!
+
 ## Running Examples
+
 We use the dedicated `dioxus-cli` to build and test dioxus web-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. If you've not used it before, `cargo install --path pacakages/dioxus-cli` will get it installed. This CLI tool should feel like using `cargo` but with 1st party support for assets, bundling, and other important dioxus-specific features.
 
 Alternatively, `trunk` works but can't run examples.

+ 0 - 0
docs/guides/01-ssr.md → docs/platforms/01-ssr.md


+ 0 - 0
docs/guides/02-wasm.md → docs/platforms/02-wasm.md


+ 0 - 0
docs/guides/03-desktop.md → docs/platforms/03-desktop.md


+ 0 - 0
docs/guides/04-concurrency.md → docs/platforms/04-concurrency.md


+ 0 - 0
docs/guides/05-liveview.md → docs/platforms/05-liveview.md


+ 0 - 0
docs/guides/06-components.md → docs/platforms/06-components.md


二進制
docs/rocketsrchrome_files/cloud-0.png


二進制
docs/rocketsrchrome_files/cloud-1.png


二進制
docs/rocketsrchrome_files/cloud-2.png


+ 0 - 1
docs/rocketsrchrome_files/config-icon.svg

@@ -1 +0,0 @@
-<svg width="57" height="57" xmlns="http://www.w3.org/2000/svg"><g fill="#FFF" fill-rule="evenodd"><path d="M28.44 49.58v-1a20.07 20.07 0 0 1-14.23-5.9 20.07 20.07 0 0 1 0-28.47 20.07 20.07 0 0 1 28.47 0 20.08 20.08 0 0 1 0 28.47 20.07 20.07 0 0 1-14.24 5.9v2a22.16 22.16 0 0 0 22.14-22.14c0-12.2-9.93-22.13-22.14-22.14A22.16 22.16 0 0 0 6.3 28.44a22.16 22.16 0 0 0 22.14 22.14v-1"/><path d="M28.44 55.89v-1c-7.29 0-13.9-2.97-18.69-7.76a26.36 26.36 0 0 1 0-37.38 26.36 26.36 0 0 1 37.38 0 26.36 26.36 0 0 1 0 37.38 26.35 26.35 0 0 1-18.69 7.76v2a28.47 28.47 0 0 0 28.44-28.45A28.47 28.47 0 0 0 28.44 0 28.47 28.47 0 0 0 0 28.44 28.47 28.47 0 0 0 28.44 56.9v-1"/><path d="M43.04 28.44h-1 .03-.03.03-.03l-.02.05a1.66 1.66 0 0 1-.27.37c-.21.25-.53.54-.85.88a4.5 4.5 0 0 0-.46.57 2.4 2.4 0 0 0-.35.8 2.25 2.25 0 0 0-.06.5c0 .34.07.64.14.91.11.42.26.79.37 1.1.1.32.16.58.15.68v.05l.08.03-.08-.04v.01l.08.03-.08-.04.03.02-.02-.02.02.02-.02-.02s-.09.08-.27.17c-.27.13-.7.27-1.18.44a5.07 5.07 0 0 0-.74.33 2.49 2.49 0 0 0-.73.6c-.31.4-.43.82-.51 1.2-.12.56-.14 1.1-.2 1.49a2.05 2.05 0 0 1-.11.43l-.04.07.03.05-.03-.05.03.05-.03-.05.04.06-.03-.06h-.01l.04.06-.03-.06s-.12.04-.32.04a7.04 7.04 0 0 1-.78-.07c-.3-.03-.64-.07-1-.07-.37 0-.78.03-1.2.24a2.6 2.6 0 0 0-.98.85c-.35.45-.6.92-.82 1.24a2.1 2.1 0 0 1-.29.34l-.07.06v.04-.04.04-.04l.01.06v-.06h-.01l.01.06v-.06a.89.89 0 0 1-.3-.1c-.27-.14-.65-.4-1.08-.66a5.08 5.08 0 0 0-.73-.36 2.55 2.55 0 0 0-.93-.2c-.47 0-.85.15-1.19.3-.49.25-.9.54-1.24.74l-.43.23a.58.58 0 0 1-.18.05v.06l.02-.06h-.02v.06l.02-.06-.02.05.02-.05-.02.05.02-.05c-.03-.02-.14-.1-.26-.26-.2-.25-.42-.64-.69-1.05a4.94 4.94 0 0 0-.48-.63 2.47 2.47 0 0 0-.73-.55c-.43-.2-.83-.24-1.2-.24-.36 0-.7.04-1 .07a7.28 7.28 0 0 1-.78.07 1.21 1.21 0 0 1-.28-.03l-.04-.01-.04.06.05-.06h-.01l-.04.06.05-.06-.03.03.03-.02-.03.02.03-.02s-.06-.1-.1-.3c-.08-.29-.1-.75-.18-1.25a5.18 5.18 0 0 0-.16-.8 2.5 2.5 0 0 0-.43-.84c-.32-.4-.7-.6-1.04-.77-.53-.23-1.04-.37-1.4-.52a2.06 2.06 0 0 1-.4-.2l-.07-.06-.04.02.04-.02-.04.02.04-.02-.07.04.08-.03-.08.03.08-.03h-.02.02-.02.02v-.05a1.6 1.6 0 0 1 .06-.38c.07-.27.2-.61.33-1 .13-.38.26-.8.26-1.31 0-.16-.01-.33-.05-.5-.12-.5-.37-.85-.61-1.15-.37-.43-.77-.78-1.03-1.07a2 2 0 0 1-.27-.36l-.04-.08v-.01h-.02.02-.02.02-.04.04-.04.04l.02-.05a1.65 1.65 0 0 1 .26-.37c.22-.24.54-.53.85-.87.16-.17.32-.36.47-.58a2.18 2.18 0 0 0 .4-1.29 3.51 3.51 0 0 0-.14-.92c-.1-.41-.26-.78-.36-1.1-.1-.32-.16-.58-.16-.68v-.05l-.07-.02.07.03-.07-.03.07.03-.03-.01.03.02-.03-.02.03.02s.08-.09.26-.17c.27-.14.71-.27 1.19-.45a5.06 5.06 0 0 0 .73-.33c.25-.14.51-.33.73-.6.32-.4.44-.82.52-1.2.11-.56.14-1.09.2-1.48.03-.2.07-.35.11-.43l.04-.08-.04-.04.04.04-.04-.04.04.04-.05-.06.04.07-.04-.07.04.07a.92.92 0 0 1 .32-.04c.2 0 .47.03.78.06.3.04.64.08 1 .08.37 0 .77-.04 1.2-.24.46-.23.74-.55.98-.85.34-.46.59-.93.82-1.25.11-.16.21-.28.28-.34l.07-.05h.01l-.01-.04v.04h.01l-.01-.04v.04-.07.07-.07.07a.89.89 0 0 1 .29.1c.27.13.65.4 1.09.65.22.13.45.26.72.37.27.1.58.19.93.19.47 0 .86-.15 1.2-.3.48-.24.9-.54 1.24-.74.17-.1.32-.18.43-.22a.58.58 0 0 1 .17-.05v-.07l-.01.06h.01v-.06l-.01.06.01-.04-.02.04.02-.04-.02.04h.01c.03.02.13.1.26.27.2.24.41.64.68 1.05.14.2.3.41.48.62.2.2.42.4.73.56.43.2.84.24 1.2.24.37 0 .7-.04 1-.08.31-.03.59-.06.79-.06l.27.02.04.02.04-.07-.04.06.04-.05-.04.05.03-.03-.04.03h.01l.03-.03-.04.03s.07.1.11.3c.07.28.1.75.17 1.25.03.25.08.51.16.79.09.27.21.57.43.85.32.39.7.6 1.05.76.52.24 1.03.37 1.4.53a2 2 0 0 1 .4.2l.06.05.05-.02-.05.02.05-.02-.05.02.08-.03-.08.02v.01l.08-.03-.08.02h.01-.01.01-.01v.05c0 .07-.02.2-.06.39l-.34 1c-.12.38-.25.8-.26 1.3 0 .17.02.34.06.51.12.5.37.84.6 1.14.38.44.78.78 1.04 1.08a2 2 0 0 1 .27.35l.03.08v.01h.03-.02.02-.02 2a2.07 2.07 0 0 0-.14-.74 3.24 3.24 0 0 0-.6-.94c-.32-.37-.66-.68-.9-.95a2.8 2.8 0 0 1-.29-.33.53.53 0 0 1-.07-.14v-.06a1.61 1.61 0 0 1 .06-.4c.07-.27.2-.61.33-.99s.26-.8.26-1.3c0-.29-.05-.6-.2-.92a2.04 2.04 0 0 0-.45-.6c-.3-.28-.62-.45-.93-.58-.46-.2-.9-.33-1.23-.46a2.83 2.83 0 0 1-.4-.18.52.52 0 0 1-.14-.1 1 1 0 0 1-.12-.35c-.07-.34-.1-.85-.18-1.4a3.94 3.94 0 0 0-.23-.87 2.15 2.15 0 0 0-.64-.88 2.08 2.08 0 0 0-.81-.39 3.16 3.16 0 0 0-.75-.08c-.37 0-.7.04-1 .07a7.43 7.43 0 0 1-.79.07.89.89 0 0 1-.33-.04s-.11-.08-.25-.26c-.21-.28-.46-.73-.78-1.19a3.93 3.93 0 0 0-.59-.68 2.17 2.17 0 0 0-.96-.52 1.89 1.89 0 0 0-.43-.04c-.47 0-.85.15-1.17.3-.48.24-.89.53-1.23.73-.17.1-.32.18-.44.23a.62.62 0 0 1-.2.05.9.9 0 0 1-.32-.1c-.28-.14-.66-.4-1.09-.66a5.13 5.13 0 0 0-.7-.36 2.47 2.47 0 0 0-.93-.2c-.14 0-.28.02-.43.06a2.05 2.05 0 0 0-.69.3 3.25 3.25 0 0 0-.78.78c-.3.4-.51.8-.72 1.1l-.26.35a.54.54 0 0 1-.13.1c0 .01-.12.05-.33.05a7.28 7.28 0 0 1-.78-.07c-.3-.03-.64-.07-1-.07-.24 0-.49.02-.75.08a2.08 2.08 0 0 0-.81.39 2.04 2.04 0 0 0-.5.57c-.2.36-.28.71-.35 1.04-.09.49-.11.95-.17 1.3a2.77 2.77 0 0 1-.09.43.53.53 0 0 1-.07.16s-.1.1-.31.2c-.32.14-.81.28-1.33.48a3.93 3.93 0 0 0-.8.42 2.15 2.15 0 0 0-.71.82 2.08 2.08 0 0 0-.2.91c0 .34.07.64.14.91.11.41.26.78.36 1.1.11.31.17.58.16.69v.06l-.04.08a2.54 2.54 0 0 1-.35.43c-.26.27-.6.58-.93.97a3.4 3.4 0 0 0-.45.68 2.15 2.15 0 0 0-.23.94 2 2 0 0 0 .14.75c.15.38.37.67.59.93.32.38.67.69.92.95.12.13.21.25.27.34a.53.53 0 0 1 .08.14v.06a1.6 1.6 0 0 1-.07.4c-.07.26-.2.6-.33.98-.12.39-.25.8-.26 1.31a2.02 2.02 0 0 0 .65 1.52c.3.28.63.44.93.58.46.2.9.32 1.24.45.17.07.3.13.4.19a.54.54 0 0 1 .13.1c.01 0 .08.12.12.35.07.33.1.85.19 1.4.04.27.1.56.23.87a2.08 2.08 0 0 0 1.45 1.27c.26.06.51.07.75.07.36 0 .7-.04 1-.07.3-.04.58-.07.78-.06.2 0 .32.03.33.04 0 0 .12.07.25.26.22.27.46.72.78 1.18.16.23.35.47.6.68a1.99 1.99 0 0 0 1.39.56c.46 0 .84-.14 1.16-.3.49-.24.9-.53 1.24-.73.17-.1.32-.18.43-.22a.63.63 0 0 1 .2-.06.9.9 0 0 1 .33.11c.28.13.65.4 1.08.65.22.13.45.26.71.36.27.1.57.2.92.2a2.01 2.01 0 0 0 1.13-.36c.34-.23.57-.5.77-.77.3-.4.52-.81.72-1.11.1-.15.2-.27.27-.35a.53.53 0 0 1 .12-.1.72.72 0 0 1 .33-.04c.2 0 .48.02.78.06.3.03.64.07 1 .07.24 0 .5-.01.76-.08a2.06 2.06 0 0 0 1.3-.96c.2-.36.29-.7.35-1.04.1-.48.12-.94.17-1.3.03-.18.06-.33.1-.43a.53.53 0 0 1 .06-.16s.1-.1.32-.19c.31-.14.8-.28 1.32-.49.26-.1.53-.23.8-.42.26-.19.54-.45.71-.82a2.07 2.07 0 0 0 .2-.9 3.5 3.5 0 0 0-.14-.92c-.1-.41-.26-.78-.36-1.1a3 3 0 0 1-.16-.68v-.07l.05-.08c.05-.1.17-.25.35-.43.25-.27.6-.58.93-.97.16-.2.32-.4.45-.68.13-.26.23-.58.23-.94h-1m-30.5-21a2.6 2.6 0 1 1-5.2 0 2.6 2.6 0 0 1 5.2 0m29.75 39a3.35 3.35 0 1 1-6.7 0 3.35 3.35 0 0 1 6.7 0"/></g></svg>

+ 0 - 1
docs/rocketsrchrome_files/cookies-icon.svg

@@ -1 +0,0 @@
-<svg width="72" height="58" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path d="M51.1 35.7a3 3 0 0 1-2.8-3c0-.4 0-.8.2-1.1l.4-1-1-.3a5.1 5.1 0 0 1-3.3-4.8l.1-1.1.3-1.2h-1.4a4.6 4.6 0 0 1-4.6-4.6V17l-1.2.4a3.2 3.2 0 0 1-1.1.2 3.3 3.3 0 0 1-3.3-3.2c0-.6.2-1.2.5-1.7l.7-1-1.2-.4a26 26 0 0 0-7.4-1 26 26 0 1 0 26 26.3v-.9h-.9z" id="b"/><filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="a"><feOffset dx="2" in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur stdDeviation=".5" in="shadowOffsetOuter1" result="shadowBlurOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0" in="shadowBlurOuter1"/></filter></defs><g fill="none" fill-rule="evenodd"><g transform="rotate(14 33.7 105.7)" fill="#FFF"><path d="M51.1 25.4a3 3 0 0 1-2.8-3c0-.3 0-.7.2-1l.4-1-1-.3a5.1 5.1 0 0 1-3.3-4.8l.1-1.2.3-1.1h-1.4A4.6 4.6 0 0 1 39 8.4V6.8l-1.2.4a3.2 3.2 0 0 1-1.1.2 3.3 3.3 0 0 1-3.3-3.2c0-.6.2-1.2.5-1.7l.7-1-1.2-.4A26 26 0 0 0 26 0a26 26 0 1 0 26 26.4v-1h-.9zM26 50.1c-7.5 0-14.3-3.4-18.7-8.9a3.2 3.2 0 1 0 .3-6.3 3.2 3.2 0 0 0-3 2.2 24 24 0 0 1-2.7-10.7 2 2 0 0 0 2 1.5 2 2 0 0 0 0-4.1 2 2 0 0 0-2 1.5 24.2 24.2 0 0 1 19.4-23l-.2 1a2.2 2.2 0 1 0 4.4 0 2.2 2.2 0 0 0-.5-1.4h1c2 0 4 .2 5.8.7a5 5 0 0 0-.2 1.6 5.1 5.1 0 0 0 5 5h.6a6.5 6.5 0 0 0 5.5 5.6 6.5 6.5 0 0 0 0 .5 7 7 0 0 0 3.8 6.2 4.8 4.8 0 0 0 3.6 5.7 24.2 24.2 0 0 1-24.1 23z" stroke="#FFF"/><ellipse cx="14.5" cy="11.4" rx="2" ry="2"/><ellipse cx="27.9" cy="14.1" rx="2.9" ry="2.9"/><ellipse cx="15.5" cy="21.6" rx="3.1" ry="3.1"/><circle cx="26.5" cy="29.5" r="3.8"/><ellipse cx="34" cy="42.5" rx="2.3" ry="2.3"/><ellipse cx="41.6" cy="32.9" rx="2" ry="2"/><circle cx="20.8" cy="41.7" r="2.6"/><ellipse cx="39.1" cy="20.7" rx="2" ry="2"/></g><g transform="translate(0 -6)"><use fill="#000" filter="url(#a)" xlink:href="#b"/><use fill="#282828" xlink:href="#b"/></g><g transform="translate(1.9 4.2)" fill="#FFF" stroke="#FFF"><path d="M51.1 25.4a3 3 0 0 1-2.8-3c0-.3 0-.7.2-1l.4-1-1-.3a5.1 5.1 0 0 1-3.3-4.8l.1-1.2.3-1.1h-1.4A4.6 4.6 0 0 1 39 8.4V6.8l-1.2.4a3.2 3.2 0 0 1-1.1.2 3.3 3.3 0 0 1-3.3-3.2c0-.6.2-1.2.5-1.7l.7-1-1.2-.4A26 26 0 0 0 26 0a26 26 0 1 0 26 26.4v-1h-.9zM26 50.1c-7.5 0-14.3-3.4-18.7-8.9a3.2 3.2 0 1 0 .3-6.3 3.2 3.2 0 0 0-3 2.2 24 24 0 0 1-2.7-10.7 2 2 0 0 0 2 1.5 2 2 0 0 0 0-4.1 2 2 0 0 0-2 1.5 24.2 24.2 0 0 1 19.4-23l-.2 1a2.2 2.2 0 1 0 4.4 0 2.2 2.2 0 0 0-.5-1.4h1c2 0 4 .2 5.8.7a5 5 0 0 0-.2 1.6 5.1 5.1 0 0 0 5 5h.6a6.5 6.5 0 0 0 5.5 5.6 6.5 6.5 0 0 0 0 .5 7 7 0 0 0 3.8 6.2 4.8 4.8 0 0 0 3.6 5.7 24.2 24.2 0 0 1-24.1 23z"/><ellipse cx="14.5" cy="11.4" rx="2" ry="2"/><ellipse cx="27.9" cy="14.1" rx="2.9" ry="2.9"/><ellipse cx="15.5" cy="21.6" rx="3.1" ry="3.1"/><ellipse cx="26.5" cy="29.5" rx="3.8" ry="3.8"/><ellipse cx="34" cy="42.5" rx="2.3" ry="2.3"/><ellipse cx="41.6" cy="32.9" rx="2" ry="2"/><ellipse cx="20.8" cy="41.7" rx="2.6" ry="2.6"/><ellipse cx="39.1" cy="20.7" rx="2" ry="2"/></g></g></svg>

+ 0 - 32
docs/rocketsrchrome_files/css

@@ -1,32 +0,0 @@
-/* latin-ext */
-@font-face {
-  font-family: 'Proza Libre';
-  font-style: normal;
-  font-weight: 400;
-  src: url(https://fonts.gstatic.com/s/prozalibre/v5/LYjGdGHgj0k1DIQRyUEyyEomdNr1Wpyyzzc.woff2) format('woff2');
-  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
-}
-/* latin */
-@font-face {
-  font-family: 'Proza Libre';
-  font-style: normal;
-  font-weight: 400;
-  src: url(https://fonts.gstatic.com/s/prozalibre/v5/LYjGdGHgj0k1DIQRyUEyyEoodNr1Wpyy.woff2) format('woff2');
-  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
-}
-/* latin-ext */
-@font-face {
-  font-family: 'Proza Libre';
-  font-style: normal;
-  font-weight: 500;
-  src: url(https://fonts.gstatic.com/s/prozalibre/v5/LYjbdGHgj0k1DIQRyUEyyELbV8_WeJGY9T6Mh1k.woff2) format('woff2');
-  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
-}
-/* latin */
-@font-face {
-  font-family: 'Proza Libre';
-  font-style: normal;
-  font-weight: 500;
-  src: url(https://fonts.gstatic.com/s/prozalibre/v5/LYjbdGHgj0k1DIQRyUEyyELbV8_YeJGY9T6M.woff2) format('woff2');
-  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
-}

+ 0 - 1
docs/rocketsrchrome_files/helmet.svg

@@ -1 +0,0 @@
-<svg width="69" height="71" xmlns="http://www.w3.org/2000/svg"><defs><filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="a"><feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowOffsetOuter1" result="shadowMatrixOuter1"/><feMerge><feMergeNode in="shadowMatrixOuter1"/><feMergeNode in="SourceGraphic"/></feMerge></filter></defs><g filter="url(#a)" fill="#FFF" fill-rule="evenodd"><path d="M61 41.5h-1.2v.2c0 3.7 0 7.1-.4 10.2a20 20 0 0 1-1.7 6.1 12.3 12.3 0 0 1-2.7 3.6 17 17 0 0 1-7.3 3.9c-3.3 1-7.6 1.4-13.1 1.4-6.5 0-11.4-.7-14.9-2-2.6-1-4.6-2.2-6-3.7a16 16 0 0 1-2.5-3.7c-.9-2.1-1.3-4.6-1.6-7.3-.2-2.7-.2-5.6-.2-8.7a25.5 25.5 0 0 1 7.4-18 25 25 0 0 1 35.6 0 25.5 25.5 0 0 1 7.4 18h2.5c0-15.5-12.4-28-27.7-28a27.9 27.9 0 0 0-27.8 28c0 3.7 0 7.2.5 10.5.3 2.5.8 4.9 1.9 7a15 15 0 0 0 3.1 4.4c2 2 4.8 3.5 8.5 4.5 3.6 1 8.1 1.6 13.8 1.6a47 47 0 0 0 15.7-2.2c3-1 5.2-2.5 7-4.2 1.2-1.4 2.2-2.9 2.9-4.5 1-2.4 1.6-5.1 1.9-8 .2-2.8.2-5.8.2-8.9v-.2h-1.2"/><path d="M61 41.5h-1.2v.2c0 3.7 0 7.1-.4 10.2a20 20 0 0 1-1.7 6.1 12.3 12.3 0 0 1-2.7 3.6 17 17 0 0 1-7.3 3.9c-3.3 1-7.6 1.4-13.1 1.4-6.5 0-11.4-.7-14.9-2-2.6-1-4.6-2.2-6-3.7a16 16 0 0 1-2.5-3.7c-.9-2.1-1.3-4.6-1.6-7.3-.2-2.7-.2-5.6-.2-8.7a25.5 25.5 0 0 1 7.4-18 25 25 0 0 1 35.6 0 25.5 25.5 0 0 1 7.4 18h2.5c0-15.5-12.4-28-27.7-28a27.9 27.9 0 0 0-27.8 28c0 3.7 0 7.2.5 10.5.3 2.5.8 4.9 1.9 7a15 15 0 0 0 3.1 4.4c2 2 4.8 3.5 8.5 4.5 3.6 1 8.1 1.6 13.8 1.6a47 47 0 0 0 15.7-2.2c3-1 5.2-2.5 7-4.2 1.2-1.4 2.2-2.9 2.9-4.5 1-2.4 1.6-5.1 1.9-8 .2-2.8.2-5.8.2-8.9v-.2h-1.2"/><path d="M55.7 54.5h-1.3a4.3 4.3 0 0 1-2.2 3.7 3.5 3.5 0 0 1-1.6.3H19a4.8 4.8 0 0 1-1.9-.3 6.2 6.2 0 0 1-2.3-1.8 4.3 4.3 0 0 1-.7-1 2.3 2.3 0 0 1-.2-.9V39.7c0-.4.1-.6.3-1 .4-.4 1-.9 1.9-1.2.8-.4 1.8-.6 2.9-.6h31.6c1.4 0 2.3.4 3 .8a2.3 2.3 0 0 1 .8 2v14.8H57V39.7a5.1 5.1 0 0 0-.5-2.2 5 5 0 0 0-2.3-2.4c-1-.5-2.3-.7-3.6-.7H19c-1.8 0-3.6.4-5 1.3-.7.4-1.4 1-1.8 1.6a4.2 4.2 0 0 0-.8 2.4v14.8c0 1 .3 1.7.7 2.5a8.2 8.2 0 0 0 6.9 4h31.6a6 6 0 0 0 2.7-.5 6.7 6.7 0 0 0 3.7-6h-1.3M37.7 5h-1.3a2 2 0 0 1-2 2 2 2 0 0 1-2.1-2 2 2 0 0 1 2-2.1 2 2 0 0 1 2 2H39c0-2.5-2-4.5-4.6-4.5-2.5 0-4.6 2-4.6 4.6A4.6 4.6 0 1 0 39 5h-1.3"/><path d="M32.3 15.3h2.5V7.6h-2.5zM19.6 19v6.4a1.3 1.3 0 0 0 1.3 1.2c.7 0 1.3-.5 1.3-1.2V19a1.3 1.3 0 0 0-1.3-1.3c-.7 0-1.3.6-1.3 1.3m26.6 0v6.4a1.3 1.3 0 0 0 1.3 1.2c.7 0 1.2-.5 1.2-1.2V19a1.3 1.3 0 0 0-1.2-1.3c-.7 0-1.3.6-1.3 1.3M7.6 52.6H6.3l.1.6.2.4h.5-.5.5-.5l1-.2h-1v.2l1-.2h-1 1.2l-1.2-.3v.3h1.2l-1.2-.3 1.2.3-1-.6a1.3 1.3 0 0 0-.2.3l1.2.3-1-.6 1 .6-.6-1c-.2 0-.4.3-.5.4l1.1.6-.6-1 .6 1v-1.2a1.2 1.2 0 0 0-.6.1l.6 1.1v-1.2H2.2v1.1l.4-1-.4-.1v1.1l.4-1-.3.6.4-.6h-.1l-.3.6.4-.6a2 2 0 0 1-.3-.2l-.5.3.5-.3-.5.3.5-.3-1 .5h1.1v-.5l-1 .5h1V37H1.4l1 .6a1.2 1.2 0 0 0 .1-.6H1.4l1 .6-1-.6.6 1 .3-.4-1-.6.7 1-.6-1 .2 1.1.4-.1-.6-1 .2 1.1-.2-.8v.8h.2l-.2-.8v.8-.3.3-.3.3l.2.1h6.2A1.3 1.3 0 0 0 9.1 37a1.3 1.3 0 0 0-.1-.6l-.3-.4a1.5 1.5 0 0 0-.4-.2 1.4 1.4 0 0 0-.6-.2 1.3 1.3 0 0 0-1 .4 1.4 1.4 0 0 0-.3.5 1.4 1.4 0 0 0 0 .5v15.7h2.5V37H7.8l1 .3a1 1 0 0 0 0-.3h-1l1 .3-1.1-.3.7 1a1.2 1.2 0 0 0 .4-.7L7.7 37l.7 1-.7-1v1c.1 0 .4 0 .7-.2l-.7-1V38v-1l-.5 1h.5v-1l-.5 1 .4-1-.7.8a1 1 0 0 0 .3.2l.4-1-.7.8.8-.8-1 .6.2.2.8-.8-1 .6 1-.7-1 .4v.3l1-.7-1 .4 1.1-.4H6.6v.4l1.2-.4H6.6h1.2l-1-.6c-.2.2-.2.4-.2.6h1.2l-1-.6 1 .6-.8-1a1.3 1.3 0 0 0-.3.4l1.1.6-.8-1 .8 1-.3-1.2a1.2 1.2 0 0 0-.5.2l.8 1-.3-1.2.3 1.1v-1.2a1.2 1.2 0 0 0-.3 0l.3 1.2v-1.2H2.2v1l.2-1h-.2v1l.2-1v.2-.2.2-.2H2l-.6-.1c-.2 0-.4 0-.7.2a1.4 1.4 0 0 0-.6.4 1.4 1.4 0 0 0-.2.8v15.7l.2.8.4.5a4.4 4.4 0 0 0 1 .6 1.8 1.8 0 0 0 .3.2h6a1.3 1.3 0 0 0 1.3-1V53l-.2-.3v-.2l-.8.1H9v-.1l-.8.1H9 7.6m59.5 0h-1.3l.1.6.2.4h.5-.5.5-.5l1-.2h-1v.2l1-.2h-1 1.2l-1.2-.3v.3h1.2l-1.2-.3 1.2.3-1-.6a1.3 1.3 0 0 0-.2.3l1.2.3-1-.6 1 .6-.6-1c-.2 0-.4.3-.5.4l1.1.6-.6-1 .6 1v-1.2a1.2 1.2 0 0 0-.6.1l.6 1.1v-1.2h-5.6v1.1l.4-1-.4-.1v1.1l.4-1-.3.6.4-.6H62l-.3.6.4-.6a2 2 0 0 1-.3-.2l-.5.3.5-.3-.5.3.5-.3-1 .5H62v-.5l-1 .5h1V37h-1l1 .6a1.2 1.2 0 0 0 .1-.6H61l1 .6-1-.6.6 1 .3-.4-1-.6.7 1-.6-1 .2 1.1a1 1 0 0 0 .4-.1l-.6-1 .2 1.1-.1-.8v.8h.1l-.1-.8v.8-.3.3-.3.3l.2.1h6.1a1.3 1.3 0 0 0 1.3-1.2 1.3 1.3 0 0 0-.1-.6l-.3-.4a1.5 1.5 0 0 0-.4-.2 1.4 1.4 0 0 0-.6-.2 1.3 1.3 0 0 0-1.3 1 1.4 1.4 0 0 0 0 .4v15.7h2.5V37h-1.1l1 .3a1 1 0 0 0 0-.3h-1l1 .3-1.1-.4.7 1a1.2 1.2 0 0 0 .4-.6l-1.1-.4.7 1-.7-1V38c.2 0 .4 0 .7-.2l-.7-1V38v-1l-.5 1h.5v-1l-.5 1 .4-1-.7.8a1 1 0 0 0 .3.2l.4-1-.7.8.8-.8-1 .6.2.2.8-.8-1 .6 1-.7-1 .4v.3l1-.7-1 .4 1.1-.4h-1.2v.4l1.2-.4h-1.2 1.2l-1-.6a1.3 1.3 0 0 0-.2.6h1.2l-1-.6 1 .6-.8-1a1.3 1.3 0 0 0-.3.4l1.1.6-.8-1 .8 1-.3-1.2a1.2 1.2 0 0 0-.5.2l.8 1-.3-1.2.3 1.1v-1.2a1.2 1.2 0 0 0-.3 0l.3 1.2v-1.2h-5.6v1l.2-1h-.2v1l.2-1v.2-.2.2-.2h-.3l-.6-.1c-.2 0-.4 0-.7.2a1.4 1.4 0 0 0-.8 1.2v15.7l.2.8.4.5a4.4 4.4 0 0 0 1 .6 1.8 1.8 0 0 0 .3.2 1.3 1.3 0 0 0 .3 0h5.6a1.3 1.3 0 0 0 1.3-1V53l-.1-.3-.1-.2-.8.1h.8v-.1l-.8.1h.8H67m-42.9-5.8l4.8-4.9a1.3 1.3 0 0 0 0-1.8 1.3 1.3 0 0 0-1.8 0L22.4 45a1.3 1.3 0 0 0 0 1.8 1.3 1.3 0 0 0 1.8 0M29 55l13.5-13.5a1.3 1.3 0 0 0 0-1.8 1.3 1.3 0 0 0-1.8 0L27.2 53.2a1.3 1.3 0 0 0 0 1.8 1.3 1.3 0 0 0 1.8 0m13.3 0l4.4-4.4a1.3 1.3 0 0 0 0-1.8 1.3 1.3 0 0 0-1.8 0l-4.4 4.4a1.3 1.3 0 0 0 0 1.8 1.3 1.3 0 0 0 1.8 0"/></g></svg>

+ 0 - 1
docs/rocketsrchrome_files/logo-small.svg

@@ -1 +0,0 @@
-<svg width="139" height="28" xmlns="http://www.w3.org/2000/svg"><defs><filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="a"><feOffset dx="-2" in="SourceAlpha" result="shadowOffsetOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowOffsetOuter1" result="shadowMatrixOuter1"/><feMerge><feMergeNode in="shadowMatrixOuter1"/><feMergeNode in="SourceGraphic"/></feMerge></filter><linearGradient x1="-18.384%" y1="118.346%" x2="91.782%" y2="8.547%" id="b"><stop offset="0%"/><stop stop-color="#FFF" offset="100%"/></linearGradient></defs><g filter="url(#a)" transform="rotate(45 103.014 54.088)" fill="none" fill-rule="evenodd"><path d="M63.563 29.254c0 1.444.367 2.725 1.1 3.793L62.1 35.615c-.272.294-.072.497.216.786l2.012 2.003c.277.294.465.475.748.187l2.78-2.778c.624.229 2.121.628 4.385.296l1.74-1.311c.13-.099.357-.245.507-.327l1.563-.855-1.253 1.266c-.12.121-.324.3-.453.398l-1.496 1.127 2.55 6.977a.45.45 0 0 0 .735.171l5.985-5.693a.455.455 0 0 0 .134-.248l1.342-7.499c1.632-1.411 3.284-3.053 4.913-4.882 9.376-10.53 10.775-18.76 10.775-22.728 0-1.307-.159-2.027-.165-2.057a.452.452 0 0 0-.365-.346c-.466-.08-11.581-1.793-26.046 12.662-.018.02-1.897 1.957-3.92 4.674l-7.428 2.065a.451.451 0 0 0-.226.147l-5.284 6.349a.452.452 0 0 0 .221.722l7.1 2.064 1.195-1.375c.106-.122.295-.308.423-.418l1.334-1.143-.945 1.48a4.67 4.67 0 0 1-.356.478l-1.258 1.447zM79.24 13.868c2.348-2.348 5.694-2.81 7.473-1.03 1.78 1.78 1.319 5.125-1.03 7.474-2.348 2.348-5.693 2.809-7.473 1.03-1.78-1.78-1.318-5.126 1.03-7.474z" fill="#FFF"/><path d="M79.225 13.894c2.348-2.349 5.694-2.81 7.473-1.03 1.78 1.78 1.319 5.125-1.03 7.473-2.348 2.349-5.693 2.81-7.473 1.03-1.78-1.78-1.318-5.125 1.03-7.473z" fill-opacity=".1" fill="url(#b)"/><path d="M62.342 40.43L9.359 93.336a.815.815 0 0 1-1.152 0l-.573-.572a.813.813 0 0 1 0-1.15l52.982-52.909a.815.815 0 0 1 1.152 0l.574.573a.813.813 0 0 1 0 1.15m-.762 6.738L8.595 100.074a.815.815 0 0 1-1.152 0l-.573-.573a.813.813 0 0 1 0-1.15l52.983-52.908a.815.815 0 0 1 1.152 0l.573.572a.813.813 0 0 1 0 1.15M2.027 94.388a.817.817 0 0 1-1.152 0L.3 93.816a.813.813 0 0 1 0-1.15l52.983-52.91a.815.815 0 0 1 1.152 0l.574.573a.813.813 0 0 1 0 1.15L2.027 94.39z" fill="#FFF"/></g></svg>

+ 0 - 1
docs/rocketsrchrome_files/robot-free.svg

@@ -1 +0,0 @@
-<svg width="78" height="71" xmlns="http://www.w3.org/2000/svg"><defs><filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="a"><feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowOffsetOuter1" result="shadowMatrixOuter1"/><feMerge><feMergeNode in="shadowMatrixOuter1"/><feMergeNode in="SourceGraphic"/></feMerge></filter></defs><g filter="url(#a)" fill="#FFF" fill-rule="evenodd"><path d="M36.24 21.208h-1.155c0 .36-.14.673-.36.901a1.15 1.15 0 0 1-1.667 0 1.286 1.286 0 0 1-.361-.9c0-.361.14-.674.36-.901.224-.228.51-.357.834-.359.324.002.61.131.833.359.221.227.361.54.361.9h2.311a3.6 3.6 0 0 0-1.016-2.515 3.468 3.468 0 0 0-2.489-1.058 3.47 3.47 0 0 0-2.49 1.058 3.604 3.604 0 0 0-1.015 2.515 3.6 3.6 0 0 0 1.016 2.515 3.469 3.469 0 0 0 2.49 1.058c.973 0 1.861-.41 2.488-1.058a3.6 3.6 0 0 0 1.016-2.515h-1.155m5.225-17.097H40.31c0 .36-.14.674-.36.902a1.152 1.152 0 0 1-1.666 0 1.287 1.287 0 0 1-.361-.902c0-.36.14-.672.36-.9a1.15 1.15 0 0 1 1.667 0c.22.228.36.54.36.9h2.312a3.6 3.6 0 0 0-1.016-2.515A3.464 3.464 0 0 0 39.117.54a3.467 3.467 0 0 0-2.49 1.057 3.605 3.605 0 0 0-1.015 2.515 3.6 3.6 0 0 0 1.016 2.516 3.467 3.467 0 0 0 2.49 1.057 3.464 3.464 0 0 0 2.488-1.057 3.6 3.6 0 0 0 1.016-2.516h-1.156m5.226 17.096h-1.156c0 .36-.14.673-.36.901a1.146 1.146 0 0 1-1.666 0 1.286 1.286 0 0 1-.361-.9c0-.361.14-.674.36-.902.224-.227.51-.356.834-.358.324.002.61.131.833.359.22.227.36.54.36.9h2.312a3.6 3.6 0 0 0-1.016-2.515 3.47 3.47 0 0 0-2.49-1.058c-.973 0-1.861.41-2.488 1.058a3.602 3.602 0 0 0-1.016 2.515 3.6 3.6 0 0 0 1.016 2.515 3.468 3.468 0 0 0 2.489 1.058c.973 0 1.862-.41 2.489-1.058a3.6 3.6 0 0 0 1.016-2.515h-1.156"/><path d="M52.94 21.116h-1.156c0 2.355-.923 4.444-2.412 5.957a8.121 8.121 0 0 1-5.809 2.431h-8.825a8.12 8.12 0 0 1-5.809-2.431c-1.489-1.513-2.412-3.602-2.413-5.957.001-2.356.924-4.445 2.413-5.957a8.12 8.12 0 0 1 5.809-2.432h8.825a8.121 8.121 0 0 1 5.809 2.432c1.489 1.512 2.412 3.601 2.412 5.957h2.312c0-2.97-1.175-5.654-3.08-7.583a10.43 10.43 0 0 0-7.453-3.12h-8.825a10.429 10.429 0 0 0-7.453 3.12c-1.905 1.93-3.081 4.613-3.08 7.583-.001 2.97 1.175 5.653 3.08 7.582a10.429 10.429 0 0 0 7.453 3.12h8.825a10.43 10.43 0 0 0 7.453-3.12c1.905-1.93 3.08-4.613 3.08-7.582H52.94m3.104 37.314v-1.157H21.956V38.182h32.933V58.43h1.155v-1.157 1.157H57.2V35.868H19.644v23.719H57.2V58.43h-1.156"/><path d="M67.282 59.298h-1.155c-.001 2.355-.925 4.444-2.414 5.956a8.12 8.12 0 0 1-5.808 2.432h-37.51a8.12 8.12 0 0 1-5.807-2.432c-1.49-1.512-2.413-3.6-2.414-5.956 0-2.356.924-4.445 2.414-5.957a8.12 8.12 0 0 1 5.808-2.432h37.509a8.12 8.12 0 0 1 5.808 2.432c1.49 1.512 2.413 3.6 2.414 5.957h2.31c.001-2.97-1.174-5.654-3.08-7.583a10.43 10.43 0 0 0-7.452-3.12h-37.51a10.43 10.43 0 0 0-7.452 3.12c-1.905 1.93-3.08 4.613-3.08 7.583 0 2.969 1.175 5.653 3.08 7.582A10.43 10.43 0 0 0 20.396 70h37.509a10.43 10.43 0 0 0 7.453-3.12c1.905-1.93 3.08-4.613 3.08-7.582h-1.156"/><path d="M20.396 63.636c-2.342 0-4.177-1.905-4.177-4.338s1.835-4.34 4.177-4.34h37.509c2.342 0 4.177 1.907 4.177 4.34s-1.835 4.338-4.177 4.338h-37.51M41.6 36.446V35.29h-4.622v-2.892h3.466v4.05H41.6V35.29v1.157h1.156v-6.363h-8.09v7.52h8.09v-1.157H41.6m-20.12 5.511L9.544 29.688 7.89 31.302l11.934 12.27m37.04 1.321L70.336 31.31l-1.64-1.63-13.471 13.582"/><path d="M5.851 27.344l-.828-.808c-.33.349-.877.593-1.411.718a5.251 5.251 0 0 1-1.147.142h-.03v.035-.036.036-.036l.003.001-.082-.002a1.96 1.96 0 0 0-1.308.467 1.766 1.766 0 0 0-.59 1.33c0 .3.069.583.18.842.062.146.285.58.915 1.227l.045.047-.046-.047a5.67 5.67 0 0 0 4.076 1.733 5.67 5.67 0 0 0 4.075-1.733 5.936 5.936 0 0 0 1.672-4.147 5.933 5.933 0 0 0-1.672-4.146l-.007-.006.005.005c-.624-.64-1.023-.863-1.182-.936a2.12 2.12 0 0 0-.874-.198 1.728 1.728 0 0 0-1.531.897 2.038 2.038 0 0 0-.244.993v.113c.002.143-.012.66-.14 1.22-.123.564-.37 1.145-.706 1.481l.827.808.828.807c.78-.811 1.12-1.784 1.306-2.587a8.15 8.15 0 0 0 .197-1.73l-.001-.109v-.003l-.415-.03.283.274a.444.444 0 0 0 .132-.244l-.415-.03.283.274-.404-.392v.572a.589.589 0 0 0 .404-.18l-.404-.392v.572-.32l-.073.312.073.008v-.32l-.073.312.028-.116-.04.114.012.002.028-.116-.04.114.004.001.244-.54-.302.511.058.029.244-.54-.302.511c.004.002.19.114.541.474a3.617 3.617 0 0 1 1.017 2.531c0 .925-.34 1.837-1.017 2.533a3.357 3.357 0 0 1-2.42 1.033 3.355 3.355 0 0 1-2.418-1.033 3.907 3.907 0 0 1-.42-.496l-.05-.076-.596.312.618-.266-.021-.046-.597.312.618-.266-.05-.118.05.118-.002-.004-.229.075h.239l-.01-.075-.229.075h.239-.552l.358.407a.575.575 0 0 0 .194-.407h-.552l.358.407-.316-.36.152.458a.486.486 0 0 0 .164-.098l-.316-.36.152.458-.087-.26.041.271.046-.011-.087-.26.041.271-.009-.062v.063h.01l-.01-.063v.063h.005c.012 0 .048.002.104.002a7.51 7.51 0 0 0 1.686-.205c.784-.192 1.741-.552 2.529-1.354l-.829-.807m66.531 0l-.828.807c.788.802 1.745 1.162 2.529 1.354a7.498 7.498 0 0 0 1.79.203h.005v-.063l-.01.062.01.001v-.063l-.01.062.069-.446-.322.293a.47.47 0 0 0 .254.153l.068-.446-.322.293.397-.363h-.547a.564.564 0 0 0 .15.363l.397-.363h-.547.299l-.292-.065-.007.065h.299l-.292-.065.107.024-.104-.034-.003.01.107.024-.104-.034-.002.004.769.33-.752-.369-.017.039.769.33-.752-.369.191.094-.186-.102-.005.008.191.094-.186-.102c-.005.008-.116.209-.47.573a3.357 3.357 0 0 1-2.419 1.033 3.357 3.357 0 0 1-2.419-1.033 3.617 3.617 0 0 1-1.017-2.533c0-.924.34-1.836 1.017-2.531.233-.24.394-.37.476-.43l.064-.043-.301-.51.244.538.057-.028-.301-.51.244.538.004-.001-.085-.247v.257c.053 0 .081-.01.085-.01l-.085-.247v.257-.531l-.212.485c.08.035.16.047.212.046v-.531l-.212.485.233-.533-.511.283a.602.602 0 0 0 .278.25l.233-.533-.511.283.347-.192-.388.09.04.102.348-.192-.388.09.193-.045-.197.022.004.024.193-.046-.197.022.07-.008-.07.004v.004l.07-.008-.07.004v.006-.002c0 .012-.002.05-.002.11.001.257.016.922.197 1.729.186.803.526 1.776 1.305 2.587l.828-.807.828-.808c-.336-.336-.583-.917-.706-1.482a5.927 5.927 0 0 1-.14-1.219v-.113a1.962 1.962 0 0 0-.454-1.296 1.712 1.712 0 0 0-.606-.447 1.782 1.782 0 0 0-.715-.147 2.1 2.1 0 0 0-.873.198c-.16.072-.56.295-1.184.936a5.932 5.932 0 0 0-1.673 4.147 5.935 5.935 0 0 0 1.672 4.147 5.67 5.67 0 0 0 4.075 1.733 5.67 5.67 0 0 0 4.076-1.733c.63-.647.852-1.081.915-1.227.11-.259.18-.542.18-.842.008-.474-.205-1-.591-1.33a1.96 1.96 0 0 0-1.308-.467l-.082.002h.003v.033-.034.034-.034l-.03.001c-.13 0-.617-.013-1.147-.142-.534-.125-1.081-.37-1.412-.718l-.828.808M37.556 11.57h2.31V6.364h-2.31zM20.8 42.231h19.644v-2.314H20.8zm0 4.629h19.644v-2.315H20.8zm31.936-4.647h-1.155a1.147 1.147 0 0 1-.322.805 1.02 1.02 0 0 1-1.48 0 1.147 1.147 0 0 1-.322-.805c0-.322.125-.601.322-.805.2-.202.452-.317.74-.318.287.001.54.116.74.318.197.204.321.483.322.805h2.31c0-.936-.37-1.797-.976-2.419a3.338 3.338 0 0 0-2.396-1.018c-.938 0-1.793.395-2.396 1.018a3.467 3.467 0 0 0-.977 2.42c0 .936.372 1.797.977 2.418a3.333 3.333 0 0 0 2.396 1.018 3.335 3.335 0 0 0 2.396-1.018 3.465 3.465 0 0 0 .977-2.419h-1.156"/></g></svg>

+ 0 - 1
docs/rocketsrchrome_files/ship-icon.svg

@@ -1 +0,0 @@
-<svg width="98" height="74" xmlns="http://www.w3.org/2000/svg"><g fill="#FFF" fill-rule="evenodd"><path d="M96.384 53.5h-1.617c-.001 1.045-.26 2.068-.793 3.11-.927 1.82-2.738 3.681-5.355 5.399-3.919 2.58-9.597 4.817-16.405 6.377C65.407 69.95 57.468 70.852 49 70.852c-12.903.003-24.582-2.102-32.892-5.426-4.155-1.657-7.459-3.622-9.643-5.69-1.094-1.032-1.908-2.085-2.44-3.125-.532-1.043-.791-2.066-.792-3.111 0-1.046.26-2.07.792-3.112.927-1.82 2.738-3.68 5.355-5.398 3.92-2.58 9.598-4.817 16.405-6.377C32.593 37.05 40.531 36.148 49 36.148c12.903-.004 24.58 2.101 32.892 5.426 4.155 1.657 7.458 3.621 9.642 5.689 1.095 1.032 1.908 2.086 2.44 3.125.533 1.042.792 2.066.793 3.112H98c0-1.568-.403-3.096-1.133-4.517-1.283-2.493-3.517-4.677-6.44-6.602-4.39-2.882-10.387-5.202-17.47-6.832C65.873 33.923 57.703 33 49 33c-13.267.004-25.28 2.135-34.12 5.66-4.419 1.77-8.055 3.882-10.665 6.343-1.304 1.231-2.352 2.556-3.083 3.98C.402 50.404-.002 51.932 0 53.5c-.002 1.567.402 3.094 1.132 4.517 1.283 2.492 3.517 4.676 6.44 6.601 4.391 2.882 10.387 5.202 17.471 6.832C32.125 73.077 40.295 74 49 74c13.266-.004 25.28-2.136 34.118-5.661 4.42-1.77 8.056-3.882 10.667-6.343 1.304-1.23 2.352-2.555 3.082-3.98.73-1.422 1.134-2.95 1.133-4.516h-1.616"/><path d="M89.78 46.567c0 .866.72 1.568 1.61 1.568.89 0 1.61-.702 1.61-1.568 0-.865-.72-1.567-1.61-1.567-.89 0-1.61.702-1.61 1.567zm-1.957 4.701a1.539 1.539 0 0 0 .226 2.206 1.64 1.64 0 0 0 2.266-.22 1.539 1.539 0 0 0-.226-2.205 1.641 1.641 0 0 0-2.266.219zM83.32 54.97a1.543 1.543 0 0 0-.504 2.162 1.637 1.637 0 0 0 2.221.49c.753-.461.978-1.43.503-2.162a1.637 1.637 0 0 0-2.22-.49zm-5.493 2.718a1.553 1.553 0 0 0-.872 2.048c.34.8 1.283 1.18 2.104.848.822-.332 1.212-1.249.872-2.048-.341-.8-1.283-1.18-2.104-.848zm-5.916 1.995c-.854.24-1.347 1.11-1.1 1.94.246.832 1.14 1.312 1.993 1.072.856-.24 1.348-1.109 1.101-1.94-.246-.832-1.138-1.311-1.994-1.072zm-6.128 1.44c-.873.169-1.44.993-1.267 1.843.173.848 1.02 1.4 1.893 1.231.872-.168 1.44-.992 1.267-1.842-.173-.849-1.021-1.4-1.893-1.232zm-6.248.977c-.882.108-1.508.891-1.398 1.75.11.86.916 1.468 1.799 1.36.882-.107 1.508-.89 1.397-1.75-.11-.858-.915-1.467-1.798-1.36zm-6.313.57c-.888.053-1.563.797-1.509 1.66.054.865.819 1.523 1.706 1.47.888-.054 1.564-.797 1.509-1.661-.055-.864-.818-1.521-1.706-1.468zm-6.344.195c-.89.002-1.609.706-1.607 1.57.002.867.725 1.567 1.614 1.565.89-.002 1.61-.705 1.607-1.57-.002-.867-.725-1.566-1.614-1.565zm-6.351-.156c-.889-.046-1.647.618-1.694 1.482-.047.865.635 1.603 1.523 1.648.888.047 1.646-.617 1.693-1.482.048-.864-.634-1.602-1.522-1.648zm-6.325-.51c-.883-.098-1.68.52-1.781 1.38-.101.86.534 1.637 1.418 1.735.883.097 1.68-.52 1.781-1.38.101-.86-.533-1.637-1.418-1.735zm-6.262-.901c-.875-.158-1.715.406-1.876 1.257-.16.851.417 1.668 1.292 1.825.874.158 1.714-.406 1.875-1.257.162-.851-.417-1.668-1.291-1.825zm-6.15-1.356c-.86-.228-1.744.264-1.978 1.1-.235.834.271 1.696 1.129 1.924.858.228 1.744-.264 1.978-1.1.234-.834-.271-1.696-1.13-1.924zm-5.94-1.914c-.827-.321-1.764.07-2.094.874-.33.804.073 1.716.9 2.037.824.321 1.762-.07 2.092-.875.33-.803-.073-1.715-.899-2.037v.001zm-5.512-2.657c-.756-.457-1.749-.232-2.218.504a1.542 1.542 0 0 0 .517 2.158 1.636 1.636 0 0 0 2.218-.503 1.543 1.543 0 0 0-.517-2.159zM5.87 51.684a1.641 1.641 0 0 0-2.263-.251 1.54 1.54 0 0 0-.258 2.202 1.64 1.64 0 0 0 2.263.251 1.54 1.54 0 0 0 .258-2.202zm22.24-25.73c2.976 1.4 10.46 4.391 20.173 4.396 5.905 0 12.634-1.114 19.63-4.375 4.502 4.369 7.453 10.212 7.996 16.71a50.737 50.737 0 0 1-4.564 2.236c-3.207 1.375-7.215 2.648-10.837 2.643-.45 0-.814.35-.814.782 0 .43.365.781.814.781 4.276-.005 8.732-1.546 12.153-3.064a52.697 52.697 0 0 0 3.335-1.629c.003.144.004.287.004.431 0 14.847-56 14.847-56 0 0-.225.003-.45.009-.674a52.741 52.741 0 0 0 3.786 1.872c3.421 1.518 7.878 3.059 12.152 3.064.45 0 .815-.35.815-.781 0-.432-.364-.782-.815-.782-3.862.006-8.165-1.445-11.467-2.918a51.002 51.002 0 0 1-4.368-2.204c.597-6.411 3.54-12.172 7.997-16.488zm1.264-1.151C34.324 20.57 40.85 18 48 18c7.162 0 13.697 2.579 18.649 6.822-6.557 2.953-12.828 3.964-18.366 3.965-6.089 0-11.29-1.227-14.963-2.454a42.813 42.813 0 0 1-3.946-1.53z"/><path d="M49.48 9.283l7.268-1.692a1.63 1.63 0 0 0 1.24-1.385 1.609 1.609 0 0 0-.884-1.626l-8.69-4.4a1.692 1.692 0 0 0-1.62.055A1.62 1.62 0 0 0 46 1.62v18.76c0 .895.74 1.62 1.655 1.62.914 0 1.655-.725 1.655-1.62l.17-11.097z"/></g></svg>

+ 0 - 1
docs/rocketsrchrome_files/streams-icon.svg

@@ -1 +0,0 @@
-<svg width="82" height="81" xmlns="http://www.w3.org/2000/svg"><g fill="#FFF" fill-rule="evenodd"><path d="M17.41 20.294c0 2.096-1.732 3.795-3.87 3.795-2.137 0-3.869-1.699-3.869-3.795s1.732-3.796 3.87-3.796c2.137 0 3.869 1.7 3.869 3.796m48.14 48.052c0 .828-.684 1.5-1.528 1.5-.846 0-1.53-.672-1.53-1.5 0-.83.684-1.5 1.53-1.5.844 0 1.529.67 1.529 1.5M35.542 55.012l-1.377.553a15.557 15.557 0 0 1 1.208 6.002c0 3.127-.95 6.18-2.685 8.76a16.045 16.045 0 0 1-7.387 5.949 16.41 16.41 0 0 1-6.12 1.185c-3.19 0-6.301-.932-8.932-2.633a15.872 15.872 0 0 1-6.064-7.247 15.558 15.558 0 0 1-1.21-6.002c0-3.128.95-6.18 2.686-8.76a16.04 16.04 0 0 1 7.388-5.949 16.406 16.406 0 0 1 6.12-1.185c3.189 0 6.3.932 8.931 2.633a15.878 15.878 0 0 1 6.065 7.247l1.377-.553 1.378-.551a18.806 18.806 0 0 0-7.182-8.58 19.46 19.46 0 0 0-17.815-1.713 19.015 19.015 0 0 0-8.747 7.044A18.607 18.607 0 0 0 0 61.579c0 2.37.46 4.781 1.43 7.106a18.804 18.804 0 0 0 7.18 8.58 19.46 19.46 0 0 0 17.816 1.713c3.71-1.487 6.697-3.99 8.747-7.044a18.6 18.6 0 0 0 3.176-10.367c0-2.37-.46-4.781-1.43-7.107l-1.377.552"/><path d="M10.119 48.911L45.309 2.78a1.441 1.441 0 0 0-.3-2.043 1.508 1.508 0 0 0-2.082.295L7.737 47.163a1.44 1.44 0 0 0 .3 2.043c.657.482 1.59.35 2.082-.295m24.25 24.432l47.034-34.516a1.44 1.44 0 0 0 .3-2.042 1.507 1.507 0 0 0-2.082-.295L32.586 71.006a1.441 1.441 0 0 0-.3 2.043 1.507 1.507 0 0 0 2.083.294m3.907-27.893l30.631-31.594a1.44 1.44 0 0 0-.053-2.064 1.51 1.51 0 0 0-2.104.052L36.12 43.439a1.44 1.44 0 0 0 .054 2.064 1.508 1.508 0 0 0 2.103-.053M25.648 75.23c-2.724-4.05-5.68-7.907-9.206-11.319-1.828-1.769-3.996-3.122-6.07-4.585-1.797-1.268-4.234-1.856-5.919-3.144-1.1-.84-2.623.347-2.123 1.59.544 1.349 1.643 1.665 2.86 2.409 2.077 1.271 3.884 3.002 5.71 4.586 4.205 3.645 7.617 8.153 10.211 13.025 1.784 3.345 6.654.583 4.537-2.562"/><path d="M35.876 60.62c-2.09.656-8.949-1.58-11.42-2.508-2.914-1.094-5.503-2.671-7.921-4.584-1.58-1.248-4.243-3.255-4.894-5.29-.747-2.33-4.626-.554-3.109 1.758 3.506 5.342 10.075 9.056 16.056 10.963 1.287.41 12.404 3.44 12.321.257-.012-.515-.607-.729-1.033-.596"/></g></svg>

+ 0 - 2033
docs/rocketsrchrome_files/style.css

@@ -1,2033 +0,0 @@
-@keyframes octocat-wave {
-  0%,
-  to {
-    transform: rotate(0);
-  }
-  20%,
-  60% {
-    transform: rotate(-25deg);
-  }
-  40%,
-  80% {
-    transform: rotate(10deg);
-  }
-}
-html {
-  line-height: 1.15;
-  -ms-text-size-adjust: 100%;
-  -webkit-text-size-adjust: 100%;
-}
-.features .col.tight .button,
-.features .col.tight button,
-body {
-  margin: 0;
-}
-article,
-aside,
-details,
-figcaption,
-figure,
-footer,
-header,
-header nav.version-select:hover options,
-main,
-menu,
-nav,
-section {
-  display: block;
-}
-h1 {
-  margin: 0.67em 0;
-  font-size: 3em;
-}
-figure {
-  margin: 1em 40px;
-}
-hr {
-  box-sizing: content-box;
-  overflow: visible;
-  border: 0;
-  height: 1px;
-  background-color: rgba(255, 255, 255, 0.25);
-}
-kbd,
-pre,
-samp {
-  font-family: monospace, monospace;
-  font-size: 1em;
-}
-a {
-  background-color: transparent;
-  -webkit-text-decoration-skip: objects;
-  color: #fff;
-  text-decoration: none;
-}
-a:active,
-a:hover {
-  outline-width: 0;
-}
-abbr[title] {
-  border-bottom: none;
-  text-decoration: underline dotted;
-}
-b,
-strong {
-  font-weight: bolder;
-}
-dfn {
-  font-style: italic;
-}
-mark {
-  background-color: #ff0;
-  color: #000;
-}
-small {
-  font-size: 80%;
-}
-sub,
-sup {
-  font-size: 75%;
-  line-height: 0;
-  position: relative;
-  vertical-align: baseline;
-}
-sub {
-  bottom: -0.25em;
-}
-sup {
-  top: -0.5em;
-}
-audio,
-canvas,
-video {
-  display: inline-block;
-}
-audio:not([controls]) {
-  display: none;
-  height: 0;
-}
-img {
-  border-style: none;
-}
-svg:not(:root) {
-  overflow: hidden;
-}
-button {
-  line-height: 1.15;
-}
-input,
-optgroup,
-select,
-textarea {
-  font-family: sans-serif;
-  line-height: 1.15;
-  margin: 0;
-}
-optgroup {
-  font-size: 100%;
-}
-button,
-input {
-  overflow: visible;
-}
-button,
-select {
-  text-transform: none;
-}
-[type="reset"],
-[type="submit"],
-button,
-html [type="button"] {
-  -webkit-appearance: button;
-}
-[type="button"]::-moz-focus-inner,
-[type="reset"]::-moz-focus-inner,
-[type="submit"]::-moz-focus-inner,
-button::-moz-focus-inner {
-  border-style: none;
-  padding: 0;
-}
-[type="button"]:-moz-focusring,
-[type="reset"]:-moz-focusring,
-[type="submit"]:-moz-focusring,
-button:-moz-focusring {
-  outline: 1px dotted ButtonText;
-}
-fieldset {
-  border: 1px solid silver;
-  margin: 0 2px;
-  padding: 0.35em 0.625em 0.75em;
-}
-legend {
-  color: inherit;
-  display: table;
-  max-width: 100%;
-  white-space: normal;
-}
-progress {
-  display: inline-block;
-  vertical-align: baseline;
-}
-textarea {
-  overflow: auto;
-}
-[type="checkbox"],
-[type="radio"],
-legend {
-  box-sizing: border-box;
-  padding: 0;
-}
-[type="number"]::-webkit-inner-spin-button,
-[type="number"]::-webkit-outer-spin-button {
-  height: auto;
-}
-[type="search"] {
-  -webkit-appearance: textfield;
-  outline-offset: -2px;
-}
-[type="search"]::-webkit-search-cancel-button,
-[type="search"]::-webkit-search-decoration {
-  -webkit-appearance: none;
-}
-::-webkit-file-upload-button {
-  -webkit-appearance: button;
-  font: inherit;
-}
-summary {
-  display: list-item;
-}
-[hidden],
-template {
-  display: none;
-}
-body,
-html {
-  -webkit-font-smoothing: antialiased;
-  background-color: black;
-  /* background-color: #d33847; */
-}
-html {
-  color: #fff;
-}
-a.button,
-body,
-button,
-html {
-  font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
-}
-body {
-  font-size: 16px;
-}
-body,
-input,
-select,
-textarea {
-  color: #fff;
-}
-.code {
-  font-family: Consolas, "Liberation Mono", Menlo, Monaco, Lucida Console,
-    Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New,
-    monospace, serif;
-}
-.container {
-  margin: 0 20px;
-  display: inherit;
-  position: relative;
-  width: calc(100% - 40px);
-}
-@media (min-width: 1310px) {
-  .container {
-    margin: auto;
-    width: 1270px;
-  }
-}
-h2 {
-  font-size: 2.5em;
-}
-h3 {
-  font-size: 1.6em;
-}
-h4 {
-  font-size: 1.2em;
-}
-.addon,
-input,
-select,
-textarea {
-  outline: 0;
-  font-size: 14px;
-}
-ul.columns {
-  list-style-position: inside;
-  columns: 1;
-}
-@media (min-width: 650px) {
-  ul.columns {
-    columns: 2;
-  }
-}
-@media (min-width: 800px) {
-  ul.columns {
-    columns: 3;
-  }
-}
-a.button,
-button {
-  font-size: 1.125em;
-  background: #999;
-  border-radius: 5px;
-  border: 0;
-  cursor: pointer;
-  display: inline-block;
-  padding: 8px 34px;
-  background: #fff;
-  color: #f03b4d;
-  font-weight: 500;
-  box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.15);
-  margin: 15px;
-  text-shadow: none;
-}
-a.button.small,
-button.small {
-  font-size: 0.875em;
-  padding: 8px 26px;
-}
-a.button:hover,
-button:hover {
-  background: #ffd1d6;
-  background: linear-gradient(#fff, #ffd1d6);
-  border: 0;
-  outline: 0;
-}
-a.button:active,
-a.button:focus,
-button:active,
-button:focus {
-  background: #ffd1d6;
-  background: linear-gradient(#ffd1d6, #fff);
-  border: 0;
-  outline: 0;
-}
-a.button.inverted,
-button.inverted {
-  background: 0 0;
-  color: #fff;
-  padding: 6px 30px;
-  border: 2px solid #fff;
-  font-weight: 500;
-}
-a.button.inverted.small,
-button.inverted.small {
-  padding: 6px 24px;
-}
-a.button.inverted:hover,
-button.inverted:hover {
-  background-color: rgba(255, 255, 255, 0.15);
-}
-a.button.inverted:active,
-a.button.inverted:focus,
-button.inverted:active,
-button.inverted:focus {
-  background-color: rgba(0, 0, 0, 0.25);
-}
-a.button.inverted.blue,
-button.inverted.blue {
-  border-color: #5daced;
-}
-a.button.inverted.purple,
-button.inverted.purple {
-  border-color: #df76ff;
-}
-a.button.inverted.red,
-button.inverted.red {
-  border-color: #ff6170;
-}
-a.button.inverted.yellow,
-button.inverted.yellow {
-  border-color: #fff776;
-}
-a.button.inverted.orange,
-button.inverted.orange {
-  border-color: #ff853e;
-}
-a.button.inverted.green,
-button.inverted.green {
-  border-color: #15dc98;
-}
-.table-container {
-  overflow-x: auto;
-}
-table:not(.code) {
-  border-collapse: collapse;
-  border-spacing: 0;
-  font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
-  text-shadow: none;
-  box-shadow: 0 2px 2px rgba(0, 0, 0, 0.25);
-  border-bottom: 1px solid #111;
-  border-top: 1px solid #111;
-}
-table:not(.code) thead {
-  background-color: #131313;
-  text-align: left;
-  border-bottom: 1px solid #111;
-}
-table:not(.code) td,
-table:not(.code) th {
-  border-left: 1px solid #111;
-  padding: 0.5em 1.25em;
-}
-table:not(.code) td:last-child,
-table:not(.code) th:last-child {
-  border-right: 1px solid #111;
-}
-table:not(.code) tbody > tr {
-  background: #303133;
-}
-table:not(.code) tbody > tr:nth-child(2n) {
-  background: #202020;
-}
-.grid {
-  display: flex;
-}
-@media (max-width: 870px) {
-  .grid {
-    display: block;
-  }
-}
-.col {
-  box-sizing: border-box;
-  flex: 1;
-}
-.col.center {
-  align-self: center;
-}
-.hl,
-.hl-dark {
-  color: #abb2bf;
-}
-.hl .c,
-.hl-dark .c {
-  color: #5c6370;
-  font-style: italic;
-}
-.hl .err,
-.hl-dark .err {
-  color: #960050;
-  background-color: #1e0010;
-}
-.hl .k,
-.hl-dark .k {
-  color: #c678dd;
-}
-.hl .l,
-.hl-dark .l {
-  color: #98c379;
-}
-.hl .n,
-.hl .o,
-.hl .p,
-.hl-dark .n,
-.hl-dark .o,
-.hl-dark .p {
-  color: #abb2bf;
-}
-.hl .cm,
-.hl-dark .cm {
-  color: #5c6370;
-  font-style: italic;
-}
-.hl .cp,
-.hl-dark .cp {
-  color: #61afef;
-}
-.hl .c1,
-.hl .cs,
-.hl-dark .c1,
-.hl-dark .cs {
-  color: #5c6370;
-  font-style: italic;
-}
-.hl .ge,
-.hl-dark .ge {
-  font-style: italic;
-}
-.hl .gs,
-.hl-dark .gs {
-  font-weight: 700;
-}
-.hl .kc,
-.hl .kd,
-.hl .kn,
-.hl-dark .kc,
-.hl-dark .kd,
-.hl-dark .kn {
-  color: #c678dd;
-}
-.hl .kp,
-.hl-dark .kp {
-  color: #d19a66;
-}
-.hl .kr,
-.hl-dark .kr {
-  color: #c678dd;
-}
-.hl .kt,
-.hl-dark .kt {
-  color: #e06c75;
-}
-.hl .ld,
-.hl-dark .ld {
-  color: #98c379;
-}
-.hl .m,
-.hl-dark .m {
-  color: #d19a66;
-}
-.hl .s,
-.hl-dark .s {
-  color: #98c379;
-}
-.hl .na,
-.hl-dark .na {
-  color: #d19a66;
-}
-.hl .nb,
-.hl .nc,
-.hl .nd,
-.hl .ne,
-.hl .ni,
-.hl .no,
-.hl-dark .nb,
-.hl-dark .nc,
-.hl-dark .nd,
-.hl-dark .ne,
-.hl-dark .ni,
-.hl-dark .no {
-  color: #e5c07b;
-}
-.hl .nf,
-.hl-dark .nf {
-  color: #61afef;
-}
-.hl .nl,
-.hl-dark .nl {
-  color: #e5c07b;
-}
-.hl .nn,
-.hl .nx,
-.hl-dark .nn,
-.hl-dark .nx {
-  color: #abb2bf;
-}
-.hl .py,
-.hl-dark .py {
-  color: #e5c07b;
-}
-.hl .nt,
-.hl-dark .nt {
-  color: #e06c75;
-}
-.hl .nv,
-.hl-dark .nv {
-  color: #e5c07b;
-}
-.hl .ow,
-.hl-dark .ow {
-  font-weight: 700;
-}
-.hl .w,
-.hl-dark .w {
-  color: #f8f8f2;
-}
-.hl .mf,
-.hl .mh,
-.hl .mi,
-.hl .mo,
-.hl-dark .mf,
-.hl-dark .mh,
-.hl-dark .mi,
-.hl-dark .mo {
-  color: #d19a66;
-}
-.hl .s2,
-.hl .sb,
-.hl .sc,
-.hl .sd,
-.hl .se,
-.hl .sh,
-.hl .si,
-.hl .sx,
-.hl-dark .s2,
-.hl-dark .sb,
-.hl-dark .sc,
-.hl-dark .sd,
-.hl-dark .se,
-.hl-dark .sh,
-.hl-dark .si,
-.hl-dark .sx {
-  color: #98c379;
-}
-.hl .sr,
-.hl-dark .sr {
-  color: #56b6c2;
-}
-.hl .s1,
-.hl-dark .s1 {
-  color: #98c379;
-}
-.hl .ss,
-.hl-dark .ss {
-  color: #56b6c2;
-}
-.hl .bp,
-.hl .vc,
-.hl .vg,
-.hl-dark .bp,
-.hl-dark .vc,
-.hl-dark .vg {
-  color: #e5c07b;
-}
-.hl .vi,
-.hl-dark .vi {
-  color: #e06c75;
-}
-.hl .il,
-.hl-dark .il {
-  color: #d19a66;
-}
-.hl .gu,
-.hl-dark .gu {
-  color: #75715e;
-}
-.hl .gd,
-.hl-dark .gd {
-  color: #f92672;
-}
-.hl .gi,
-.hl-dark .gi {
-  color: #a6e22e;
-}
-.hl-light {
-  color: #383a42;
-}
-.hl-light .c {
-  color: #a0a1a7;
-  font-style: italic;
-}
-.hl-light .err {
-  color: #960050;
-  background-color: #1e0010;
-}
-.hl-light .k {
-  color: #a626a4;
-}
-.hl-light .l {
-  color: #50a14f;
-}
-.hl-light .n,
-.hl-light .o,
-.hl-light .p {
-  color: #383a42;
-}
-.hl-light .cm {
-  color: #a0a1a7;
-  font-style: italic;
-}
-.hl-light .cp {
-  color: #4078f2;
-}
-.hl-light .c1,
-.hl-light .cs {
-  color: #a0a1a7;
-  font-style: italic;
-}
-.hl-light .ge {
-  font-style: italic;
-}
-.hl-light .gs {
-  font-weight: 700;
-}
-.hl-light .kc,
-.hl-light .kd,
-.hl-light .kn {
-  color: #a626a4;
-}
-.hl-light .kp {
-  color: #986801;
-}
-.hl-light .kr {
-  color: #a626a4;
-}
-.hl-light .kt {
-  color: #e45649;
-}
-.hl-light .ld {
-  color: #50a14f;
-}
-.hl-light .m {
-  color: #986801;
-}
-.hl-light .s {
-  color: #50a14f;
-}
-.hl-light .na {
-  color: #986801;
-}
-.hl-light .nb,
-.hl-light .nc,
-.hl-light .nd,
-.hl-light .ne,
-.hl-light .ni,
-.hl-light .no {
-  color: #c18401;
-}
-.hl-light .nf {
-  color: #4078f2;
-}
-.hl-light .nl {
-  color: #c18401;
-}
-.hl-light .nn,
-.hl-light .nx {
-  color: #383a42;
-}
-.hl-light .py {
-  color: #c18401;
-}
-.hl-light .nt {
-  color: #e45649;
-}
-.hl-light .nv {
-  color: #c18401;
-}
-.hl-light .ow {
-  font-weight: 700;
-}
-.hl-light .w {
-  color: #f8f8f2;
-}
-.hl-light .mf,
-.hl-light .mh,
-.hl-light .mi,
-.hl-light .mo {
-  color: #986801;
-}
-.hl-light .s2,
-.hl-light .sb,
-.hl-light .sc,
-.hl-light .sd,
-.hl-light .se,
-.hl-light .sh,
-.hl-light .si,
-.hl-light .sx {
-  color: #50a14f;
-}
-.hl-light .sr {
-  color: #0184bc;
-}
-.hl-light .s1 {
-  color: #50a14f;
-}
-.hl-light .ss {
-  color: #0184bc;
-}
-.hl-light .bp,
-.hl-light .vc,
-.hl-light .vg {
-  color: #c18401;
-}
-.hl-light .vi {
-  color: #e45649;
-}
-.hl-light .il {
-  color: #986801;
-}
-.hl-light .gu {
-  color: #75715e;
-}
-.hl-light .gd {
-  color: #f92672;
-}
-.hl-light .gi {
-  color: #a6e22e;
-}
-header {
-  background-color: #d33847;
-  position: relative;
-  overflow: hidden;
-}
-header :not(.cloud) {
-  position: relative;
-  z-index: 10;
-}
-header h1,
-header h2,
-header h3,
-header h4 {
-  font-family: "Proza Libre", "Helvetica Neue", Helvetica, Arial,
-    "Lucida Grande", sans-serif;
-  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.25);
-}
-header h1 {
-  font-size: 42px;
-  margin: 30px 0 0;
-  font-weight: 600;
-}
-header h1 a:active,
-header h1 a:focus,
-header h1 a:hover {
-  color: #ffbec4;
-  border: 0;
-}
-header h4 {
-  font-size: 16px;
-  line-height: 18px;
-  font-weight: 500;
-  margin: 0;
-  padding: 10px 0 70px;
-  color: #ffdada;
-}
-header .banner {
-  margin: 30px 0 50px;
-}
-header .banner h1,
-header .banner h2,
-header .banner h3,
-header .banner h4 {
-  font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
-}
-header .banner h1 {
-  font-size: 36px;
-  font-weight: 500;
-  margin: 17px 0;
-}
-header .banner h2 {
-  font-size: 25px;
-  font-weight: 300;
-  line-height: 36px;
-  margin: 10px auto 15px;
-  max-width: 580px;
-}
-.cloud {
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  display: block;
-  -webkit-backface-visibility: hidden;
-  -moz-backface-visibility: hidden;
-  -ms-backface-visibility: hidden;
-  backface-visibility: hidden;
-  -webkit-perspective: 1000;
-  -moz-perspective: 1000;
-  -ms-perspective: 1000;
-  perspective: 1000;
-  transform: translateZ(0);
-}
-.cloud.back {
-  z-index: 1;
-  opacity: 0.03;
-}
-.cloud.front {
-  z-index: 2;
-  opacity: 0.06;
-}
-.features img {
-  margin-bottom: 15px;
-}
-.features h2 {
-  font-size: 36px;
-  color: #fff;
-  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.15);
-  font-weight: 500;
-  line-height: 36px;
-  margin-top: 0;
-  margin-bottom: 10px;
-}
-.features figcaption,
-.features h2,
-.features h3,
-.features h4 {
-  font-family: "Proza Libre", "Helvetica Neue", Helvetica, Arial,
-    "Lucida Grande", sans-serif;
-}
-.features h3 {
-  font-size: 20px;
-  line-height: 20px;
-  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
-  margin: 0 auto;
-  font-weight: 500;
-}
-.features h3.blue {
-  color: #5daced;
-}
-.features h3.purple {
-  color: #df76ff;
-}
-.features h3.red {
-  color: #ff6170;
-}
-.features h3.yellow {
-  color: #fff776;
-}
-.features h3.orange {
-  color: #ff853e;
-}
-.features h3.green {
-  color: #15dc98;
-}
-.features figcaption,
-.features h4 {
-  font-weight: 400;
-}
-.features h4 {
-  margin-top: 0;
-  margin-bottom: 35px;
-  font-size: 18px;
-  color: #a2a2a2;
-  line-height: 24px;
-}
-.features figcaption {
-  color: #ffd5d8;
-  font-size: 15px;
-  line-height: 25px;
-  max-width: 220px;
-  margin: 10px auto 0;
-}
-.features figcaption.wide {
-  margin-bottom: 15px;
-  max-width: 300px;
-  font-weight: 300;
-  color: #fff;
-  padding: 0 10px;
-}
-.features .col {
-  border-right: 1px solid rgba(255, 255, 255, 0.25);
-  margin: 40px 0;
-}
-@media (max-width: 870px) {
-  .features .col {
-    border-right: none;
-  }
-}
-.features .col.tight:last-child,
-.features .col:last-child {
-  border-right: none;
-}
-@media (max-width: 870px) {
-  .features .col:last-child {
-    margin-bottom: 40px;
-  }
-}
-.features .col.tight {
-  padding: 35px 0;
-  margin: 10px 0;
-  border-right: 1px solid rgba(255, 255, 255, 0.1);
-}
-@media (max-width: 870px) {
-  .features .col.tight {
-    border-right: none;
-  }
-}
-@media (max-width: 870px) {
-  .features .col.tight:last-child {
-    margin-bottom: 0;
-  }
-}
-.features hr {
-  background-color: rgba(255, 255, 255, 0.1);
-  margin: 30px 0;
-}
-a:hover {
-  border-bottom: 1px dashed #fff;
-}
-a:active,
-a:focus {
-  border-bottom: 1px solid #fff;
-  outline: 0;
-}
-#pagination ul,
-.centered,
-.circle-container h4 {
-  text-align: center;
-}
-.pull-right {
-  float: right;
-}
-.text-right {
-  text-align: right;
-}
-table {
-  width: 100%;
-}
-table.code {
-  display: inline-block;
-  color: #a5abb8;
-  font-size: 14px;
-  text-shadow: none;
-  padding: 0;
-  border-spacing: 0;
-  box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.5);
-  border-radius: 5px;
-  width: 100%;
-  overflow-x: auto;
-}
-table.code * {
-  font-family: Consolas, "Liberation Mono", Menlo, Monaco, Lucida Console,
-    Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New,
-    monospace, serif;
-  line-height: 18px;
-  margin: 0;
-  -webkit-font-smoothing: subpixel-antialiased;
-}
-table.code td.linenos {
-  background-color: #3a3a3a;
-  padding: 15px 10px 15px 18px;
-  color: #666;
-  text-align: right;
-  border-top-left-radius: 5px;
-  border-bottom-left-radius: 5px;
-  border: 1px solid #4b4b4b;
-  border-right: 1px solid #1b1d22;
-}
-table.code td.code {
-  padding-left: 15px;
-  background: #323232;
-  border-top-right-radius: 5px;
-  border-bottom-right-radius: 5px;
-  border: 1px solid #4b4b4b;
-  border-left: none;
-  width: 100%;
-}
-footer,
-section {
-  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.25);
-  background-color: #272727;
-}
-section {
-  padding: 70px 0;
-}
-footer.tight,
-section.tight {
-  padding: 0;
-}
-footer.dark,
-section.dark {
-  background-color: #1d1d1d;
-}
-footer h3,
-section h3 {
-  font-size: 36px;
-  font-weight: 500;
-  margin: 20px 0 0;
-  line-height: 48px;
-}
-footer .col.left-main,
-section .col.left-main {
-  line-height: 22px;
-  align-self: center;
-}
-footer .col.left-main h3,
-footer .col.left-main p,
-section .col.left-main h3,
-section .col.left-main p {
-  padding: 0 20px;
-}
-footer .col.right-main,
-section .col.right-main {
-  overflow-x: auto;
-  align-self: center;
-}
-@media (max-width: 870px) {
-  footer h3,
-  section h3 {
-    margin: -10px 0 0;
-    text-align: center;
-  }
-  footer span.callout,
-  section span.callout {
-    display: block;
-    text-align: center;
-  }
-  footer .col.left-main,
-  section .col.left-main {
-    padding-bottom: 10px;
-  }
-}
-@media (min-width: 870px) {
-  footer:nth-child(even) .col.left-main,
-  section:nth-child(even) .col.left-main {
-    padding-left: 20px;
-  }
-  footer:nth-child(even) .col.right-main,
-  section:nth-child(even) .col.right-main {
-    padding-right: 20px;
-    order: -1;
-  }
-  footer:nth-child(odd) .col.left-main,
-  section:nth-child(odd) .col.left-main {
-    padding-right: 20px;
-  }
-  footer:nth-child(odd) .col.right-main,
-  section:nth-child(odd) .col.right-main {
-    padding-left: 20px;
-  }
-}
-footer:nth-child(odd),
-section:nth-child(odd) {
-  background-color: #d33847;
-}
-footer:nth-child(odd) table.code,
-section:nth-child(odd) table.code {
-  border-color: #a0a0a0;
-  color: #222;
-}
-footer:nth-child(odd) table.code td.linenos,
-section:nth-child(odd) table.code td.linenos {
-  background-color: #efefef;
-  border: 1px solid #a0a0a0;
-  border-right: 1px solid #d5d5d5;
-  color: #a9a9a9;
-}
-footer:nth-child(odd) table.code td.code,
-section:nth-child(odd) table.code td.code {
-  background: #fff;
-  border: 1px solid #a0a0a0;
-  border-left: none;
-}
-footer #sidebar,
-section #sidebar {
-  background-color: #1d1d1d;
-  width: calc(280px + (100% - 1310px) / 2);
-  min-width: 280px;
-}
-@media (max-width: 870px) {
-  footer #sidebar,
-  section #sidebar {
-    display: none;
-  }
-}
-footer #search-results,
-footer article,
-section #search-results,
-section article {
-  width: calc(100% - 280px);
-  max-width: 1060px;
-  padding: 40px;
-}
-@media (max-width: 870px) {
-  footer #search-results,
-  footer article,
-  section #search-results,
-  section article {
-    width: 100%;
-    padding: 35px 30px;
-  }
-}
-footer nav,
-section nav {
-  padding: 40px 35px;
-  box-sizing: border-box;
-  font-family: "Proza Libre", "Helvetica Neue", Helvetica, Arial,
-    "Lucida Grande", sans-serif;
-  font-weight: 500;
-  position: relative;
-  min-width: 250px;
-  float: right;
-  display: inline-block;
-  overflow: auto;
-}
-footer nav .affix,
-section nav .affix {
-  position: fixed;
-  top: 40px;
-  overflow: auto;
-  height: 100%;
-}
-footer nav .affix-bottom,
-section nav .affix-bottom {
-  position: relative;
-  bottom: 40px;
-  overflow: auto;
-  height: 100%;
-}
-footer nav li,
-section nav li {
-  list-style: none;
-}
-footer nav .toc ul,
-section nav .toc ul {
-  padding: 10px 0 0;
-}
-footer nav .toc ul:first-child,
-section nav .toc ul:first-child {
-  padding: 0;
-  margin: 0;
-}
-footer nav .toc ul.small,
-section nav .toc ul.small {
-  padding: 0;
-}
-footer nav .toc ul.small a,
-section nav .toc ul.small a {
-  font-size: 14px;
-}
-footer nav .toc > ul > li,
-section nav .toc > ul > li {
-  font-size: 20px;
-  line-height: 20px;
-  margin: 20px 0;
-}
-footer nav .toc > ul > li:first-child,
-section nav .toc > ul > li:first-child {
-  margin: 0;
-}
-footer nav .toc > ul > li ul li,
-section nav .toc > ul > li ul li {
-  border-left: 1px solid #424242;
-  padding: 10px 0 10px 17px;
-  font-size: 14px;
-  line-height: 14px;
-}
-footer nav .toc > ul > li ul li a,
-section nav .toc > ul > li ul li a {
-  color: #c5c5c5;
-}
-article.news a > h2,
-footer nav .toc > ul > li ul li a.active,
-footer nav .toc > ul > li ul li a:hover,
-section nav .toc > ul > li ul li a.active,
-section nav .toc > ul > li ul li a:hover {
-  color: #fff;
-}
-footer nav .toc > ul > li ul li a:active,
-footer nav .toc > ul > li ul li a:focus,
-section nav .toc > ul > li ul li a:active,
-section nav .toc > ul > li ul li a:focus {
-  color: #444;
-}
-footer nav a:hover,
-section nav a:hover {
-  border: 0;
-  text-decoration: underline;
-  color: #fff;
-}
-footer nav a:active,
-footer nav a:focus,
-section nav a:active,
-section nav a:focus {
-  border: 0;
-  color: #444;
-}
-footer nav a.active,
-section nav a.active {
-  font-weight: 700;
-}
-#search-results,
-article,
-main {
-  box-sizing: border-box;
-  padding: 40px 10px;
-  font-size: 16px;
-  font-family: Helvetica, Arial, "Lucida Grande", sans-serif;
-  line-height: 24px;
-}
-#search-results p,
-article p,
-main p {
-  margin: 15px 0;
-}
-#search-results h2,
-#search-results h3,
-#search-results h4,
-#search-results h5,
-article h2,
-article h3,
-article h4,
-article h5,
-main h2,
-main h3,
-main h4,
-main h5 {
-  font-family: "Proza Libre", "Helvetica Neue", Helvetica, Arial,
-    "Lucida Grande", sans-serif;
-  font-weight: 600;
-  text-align: left;
-}
-#search-results h2 + p,
-#search-results h3 + p,
-#search-results h4 + p,
-#search-results h5 + p,
-article h2 + p,
-article h3 + p,
-article h4 + p,
-article h5 + p,
-main h2 + p,
-main h3 + p,
-main h4 + p,
-main h5 + p {
-  margin-top: 0;
-}
-#search-results h2:first-child,
-#search-results h3:first-child,
-#search-results h4:first-child,
-#search-results h5:first-child,
-article h2:first-child,
-article h3:first-child,
-article h4:first-child,
-article h5:first-child,
-main h2:first-child,
-main h3:first-child,
-main h4:first-child,
-main h5:first-child {
-  padding-top: 0;
-  margin-top: 0;
-}
-#pagination li,
-#search-results h2:hover > a,
-#search-results h3:hover > a,
-#search-results h4:hover > a,
-#search-results h5:hover > a,
-article h2:hover > a,
-article h3:hover > a,
-article h4:hover > a,
-article h5:hover > a,
-main h2:hover > a,
-main h3:hover > a,
-main h4:hover > a,
-main h5:hover > a {
-  display: inline;
-}
-#search-results h2,
-article h2,
-main h2 {
-  padding: 20px 0 10px;
-  margin: 15px 0;
-  font-size: 30px;
-  line-height: 32px;
-}
-#search-results h3,
-article h3,
-main h3 {
-  padding: 10px 0;
-  margin: 20px 0 10px;
-  font-size: 22px;
-  line-height: 24px;
-}
-#search-results h4,
-#search-results h5,
-article h4,
-article h5,
-main h4,
-main h5 {
-  padding: 10px 0;
-  margin: 10px 0 5px;
-}
-#search-results h4,
-article h4,
-main h4 {
-  font-size: 18px;
-  line-height: 20px;
-}
-#search-results h5,
-article h5,
-article.news h5,
-main h5 {
-  font-size: 16px;
-  line-height: 20px;
-}
-#search-results a.headerlink,
-article a.headerlink,
-main a.headerlink {
-  color: #5e5e5e;
-  font-size: 0.8em;
-  line-height: 1em;
-  margin-left: 5px;
-  border-bottom: none;
-}
-@media (min-width: 870px) {
-  #search-results a.headerlink,
-  article a.headerlink,
-  main a.headerlink {
-    display: none;
-  }
-}
-#search-results a.headerlink:active,
-#search-results a.headerlink:focus,
-#search-results a.headerlink:hover,
-article a.headerlink:active,
-article a.headerlink:focus,
-article a.headerlink:hover,
-main a.headerlink:active,
-main a.headerlink:focus,
-main a.headerlink:hover {
-  border: 0;
-}
-#search-results a.headerlink:hover,
-article a.headerlink:hover,
-main a.headerlink:hover {
-  color: #ccc;
-}
-#search-results a.headerlink:active,
-#search-results a.headerlink:focus,
-article a.headerlink:active,
-article a.headerlink:focus,
-main a.headerlink:active,
-main a.headerlink:focus {
-  color: #fff;
-}
-#search-results blockquote,
-article blockquote,
-main blockquote {
-  background-color: rgba(255, 255, 255, 0.05);
-  margin: 0;
-  padding: 5px 20px 5px 30px;
-  border-left: 10px solid rgba(255, 255, 255, 0.1);
-  box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.5);
-  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.25);
-}
-article.news {
-  font-size: 18px;
-  font-family: Helvetica, Arial, "Lucida Grande", sans-serif;
-  line-height: 30px;
-  max-width: 900px;
-  margin: 0 auto;
-  overflow-x: auto;
-}
-@media (max-width: 870px) {
-  article.news {
-    padding: 10px 5px;
-  }
-}
-article.news p:not(:nth-child(2)) {
-  margin-left: auto;
-  margin-right: auto;
-}
-article.news p.metadata {
-  margin: -10px 0 20px;
-  font-size: 16px;
-  color: #bbb;
-}
-article.news blockquote p:not(:last-child) {
-  color: #bbb;
-}
-article.news a > h2:hover {
-  text-decoration: none;
-}
-#tabs-panel .panel,
-#tabs-panel input,
-article.news h2 a,
-article.news h2:hover > a {
-  display: none;
-}
-article.news h2 {
-  margin-top: 20px;
-  font-size: 30px;
-  line-height: 42px;
-  padding: 0;
-}
-article.news h3 {
-  font-size: 22px;
-  line-height: 26px;
-}
-article.news h4 {
-  font-size: 18px;
-  line-height: 22px;
-}
-#search-results a,
-article a {
-  font-weight: 700;
-  color: #8ab4ff;
-}
-#search-results a:hover,
-article a:hover {
-  color: inherit;
-  border-bottom: none;
-  text-decoration: underline;
-}
-#search-results a:hover code,
-article a:hover code {
-  text-decoration: underline;
-}
-#search-results a:active,
-#search-results a:focus,
-article a:active,
-article a:focus {
-  border-bottom: none;
-  text-decoration: underline;
-}
-#search-results h2,
-article h2 {
-  border-bottom: 1px solid rgba(255, 255, 255, 0.15);
-}
-#search-results h3,
-article h3 {
-  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
-}
-main h2,
-main h3 {
-  margin-bottom: 0;
-}
-main h2:not(:first-child) {
-  margin-top: 30px;
-}
-code,
-footer {
-  text-shadow: none;
-}
-code {
-  display: inline-block;
-  background: rgba(0, 0, 0, 0.4);
-  font-size: 0.87em;
-  border-radius: 5px;
-  font-family: Consolas, "Liberation Mono", Menlo, Monaco, Lucida Console,
-    Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New,
-    monospace, serif;
-  -webkit-font-smoothing: subpixel-antialiased;
-  padding: 1px 4px;
-  line-height: 1.4em;
-}
-span.orange,
-span.purple {
-  color: #f68500;
-  font-weight: 400;
-  font-size: 0.95em;
-}
-span.purple {
-  color: #9a64c0;
-}
-span.callout {
-  display: inline-block;
-  background: #fff;
-  color: #000;
-  padding: 2px 15px;
-  font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
-  font-size: 14px;
-  font-weight: 700;
-  border-radius: 5px;
-  border: 1px solid #000;
-  box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.5);
-  margin: 0;
-  text-shadow: none;
-}
-footer {
-  padding: 40px 0 30px;
-  line-height: 32px;
-}
-footer,
-footer a {
-  font-size: 14px;
-  color: #ffb9b9;
-}
-footer h2 {
-  font-size: 36px;
-  font-family: "Proza Libre", "Helvetica Neue", Helvetica, Arial,
-    "Lucida Grande", sans-serif;
-}
-footer h4 {
-  font-size: 18px;
-}
-#tabs-panel {
-  border: 1px solid #3d3d3d;
-  text-shadow: none;
-  box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.5);
-}
-#tabs-panel p:first-child {
-  margin-top: 0;
-}
-#tabs-panel p:last-child {
-  margin-bottom: 0;
-}
-#tabs-panel .tab {
-  display: block;
-  padding: 17px 20px 17px 45px;
-  font: 500 18px "Proza Libre", "Helvetica Neue", Helvetica, Arial,
-    "Lucida Grande", sans-serif;
-  cursor: pointer;
-  color: #464646;
-  background-color: #212121;
-  border-right: 1px solid #3d3d3d;
-  position: relative;
-  margin-right: -1px;
-  box-shadow: inset -1px 1px 3px rgba(0, 0, 0, 0.25);
-}
-#tabs-panel .tab img {
-  margin: auto 0;
-  position: absolute;
-  left: 17px;
-  bottom: 0;
-  right: 0;
-  top: 0;
-  opacity: 0.15;
-  pointer-events: none;
-}
-#tabs-panel .tab:not(:first-child) {
-  border-top: 1px solid #2f2f2f;
-}
-#tabs-panel .tab:hover {
-  background-color: #272727;
-  color: #aaa;
-}
-#tabs-panel .tab:hover img {
-  opacity: 0.5;
-}
-#tabs-panel .tab:focus {
-  background-color: #111;
-}
-#tabs-panel .tab:active {
-  background-color: #2c2c2c;
-}
-#tabs-panel .tabs {
-  flex: 1 1 300px;
-  background-color: #212121;
-  min-width: 220px;
-}
-#tabs-panel .panels {
-  background-color: #323232;
-  width: 100%;
-}
-#tabs-panel .panel {
-  padding: 15px 25px;
-  font: 16px Helvetica, Arial, "Lucida Grande", sans-serif;
-  color: #e0e0e0;
-  line-height: 26px;
-}
-#tabs-panel #dynamic-params-tab img {
-  top: -1px;
-}
-#tabs-panel #handling-data-tab img {
-  left: 18px;
-  top: -1px;
-}
-#tabs-panel #request-guards-tab img {
-  left: 19px;
-  top: -3px;
-}
-#tabs-panel #responders-tab img {
-  top: -3px;
-}
-#tabs-panel #launching-tab img {
-  left: 21px;
-  top: -3px;
-}
-#tabs-panel #dynamic-params:checked ~ .tabs #dynamic-params-tab,
-#tabs-panel #handling-data:checked ~ .tabs #handling-data-tab,
-#tabs-panel #launching:checked ~ .tabs #launching-tab,
-#tabs-panel #request-guards:checked ~ .tabs #request-guards-tab,
-#tabs-panel #responders:checked ~ .tabs #responders-tab,
-#tabs-panel #routing:checked ~ .tabs #routing-tab {
-  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.25);
-  background-color: #323232;
-  cursor: default;
-  color: #fff;
-  border-right: none;
-  box-shadow: none;
-}
-#tabs-panel #dynamic-params:checked ~ .tabs #dynamic-params-tab img,
-#tabs-panel #handling-data:checked ~ .tabs #handling-data-tab img,
-#tabs-panel #launching:checked ~ .tabs #launching-tab img,
-#tabs-panel #request-guards:checked ~ .tabs #request-guards-tab img,
-#tabs-panel #responders:checked ~ .tabs #responders-tab img,
-#tabs-panel #routing:checked ~ .tabs #routing-tab img {
-  opacity: 1;
-}
-#tabs-panel #dynamic-params:checked ~ .panels #dynamic-params-panel,
-#tabs-panel #handling-data:checked ~ .panels #handling-data-panel,
-#tabs-panel #launching:checked ~ .panels #launching-panel,
-#tabs-panel #request-guards:checked ~ .panels #request-guards-panel,
-#tabs-panel #responders:checked ~ .panels #responders-panel,
-#tabs-panel #routing:checked ~ .panels #routing-panel {
-  display: block;
-}
-#logo span,
-#toggle {
-  display: none;
-}
-header .container {
-  padding-top: 35px;
-  z-index: 10;
-}
-header nav.version-select {
-  position: relative;
-  display: inline-block;
-  width: 70px;
-  height: 35px;
-  line-height: 35px;
-  text-align: center;
-  font-size: 15px;
-  font-family: "Proza Libre", "Helvetica Neue", Helvetica, Arial,
-    "Lucida Grande", sans-serif;
-  font-weight: 700;
-  z-index: 20;
-}
-header nav.version-select i {
-  border: solid #fff;
-  border-width: 0 3px 3px 0;
-  display: inline-block;
-  padding: 3px;
-  transform: rotate(45deg);
-  margin-left: 3px;
-  top: -2px;
-}
-header nav.version-select options {
-  display: none;
-  position: absolute;
-  box-shadow: 0 2px 0 rgba(0, 0, 0, 0.25);
-  left: -1px;
-  top: 35px;
-  z-index: 30;
-}
-header nav.version-select options a,
-header nav.version-select options a:hover {
-  border: 1px solid rgba(255, 255, 255, 0.8);
-}
-header nav.version-select options a:hover:not(:first-child),
-header nav.version-select options a:not(:first-child) {
-  border-top: none;
-}
-header nav.version-select options a {
-  color: #fff;
-  font-size: 15px;
-  font-weight: 700;
-  display: block;
-  background-color: rgba(255, 255, 255, 0.1);
-  width: 70px;
-  height: 35px;
-}
-header nav.version-select options a:hover {
-  background-color: rgba(255, 255, 255, 0.8);
-  color: #d33847;
-}
-@media (max-width: 870px) {
-  header nav.version-select options a {
-    background-color: #d44756;
-  }
-  header nav.version-select options a:hover {
-    background-color: #dcdcdc;
-  }
-}
-header .hamburger,
-header nav.main {
-  float: right;
-}
-.circle-container .circle + h4,
-header nav a {
-  font-family: "Proza Libre", "Helvetica Neue", Helvetica, Arial,
-    "Lucida Grande", sans-serif;
-}
-header nav a {
-  font-size: 18px;
-  font-weight: 500;
-}
-a#logo:active,
-a#logo:hover {
-  border: 0;
-  text-decoration: none;
-}
-@media (min-width: 870px) {
-  header nav.main {
-    margin-top: 20px;
-  }
-  header nav.main a {
-    margin-left: 35px;
-  }
-  #logo {
-    height: 60px;
-    width: 180px;
-    background-repeat: no-repeat;
-    display: inline-block;
-    vertical-align: middle;
-  }
-}
-@media (max-width: 870px) {
-  @-webkit-keyframes bugfix {
-    0%,
-    to {
-      padding: 0;
-    }
-  }
-  body {
-    -webkit-animation: bugfix infinite 1s;
-  }
-  #logo {
-    height: 30px;
-    width: 140px;
-    background-repeat: no-repeat;
-    display: inline-block;
-    vertical-align: middle;
-  }
-  header .banner {
-    margin-top: 20px;
-  }
-  header .banner h1 {
-    margin-top: 0;
-  }
-  header nav.main {
-    display: block;
-    color: #000;
-    width: 100%;
-    background-color: rgba(0, 0, 0, 0.2);
-    max-height: 0;
-    transition: max-height 0.25s ease-in-out;
-    margin: 20px 0 0;
-    overflow: hidden;
-    float: none;
-  }
-  header nav.main a {
-    display: block;
-    margin: 0;
-    padding: 15px 35px;
-  }
-  header nav.main a:first-child {
-    padding-top: 30px;
-  }
-  header nav.main a:last-child {
-    padding-bottom: 30px;
-  }
-  header nav.main a:hover {
-    border: 0;
-    background-color: rgba(0, 0, 0, 0.2);
-  }
-  header nav.main a:active,
-  header nav.main a:focus {
-    border: 0;
-    background-color: rgba(0, 0, 0, 0.4);
-  }
-  .hamburger,
-  .hamburger span {
-    display: block;
-    transform: rotate(0deg);
-  }
-  .hamburger {
-    float: right;
-    cursor: pointer;
-    user-select: none;
-    background: rgba(0, 0, 0, 0.2);
-    width: 38px;
-    height: 30px;
-    position: relative;
-  }
-  .hamburger span {
-    position: absolute;
-    height: 14%;
-    width: 60%;
-    background: #fff;
-    border-radius: 9px;
-    opacity: 1;
-    left: 20%;
-    transition: 0.25s ease-in-out;
-  }
-  .hamburger span:nth-child(1) {
-    top: 20%;
-  }
-  #toggle:checked ~ .hamburger span:nth-child(1) {
-    top: 43%;
-    transform: rotate(135deg);
-  }
-  .hamburger span:nth-child(2) {
-    top: 43%;
-  }
-  #toggle:checked ~ .hamburger span:nth-child(2) {
-    opacity: 0;
-    left: -60px;
-  }
-  .hamburger span:nth-child(3) {
-    top: 66%;
-  }
-  #toggle:checked ~ .hamburger span:nth-child(3) {
-    top: 43%;
-    transform: rotate(-135deg);
-  }
-  #toggle:checked ~ nav {
-    max-height: 300px;
-  }
-  .mobile-hide {
-    display: none;
-  }
-}
-.circle-container {
-  flex: 0 0 180px;
-}
-.circle-container .circle {
-  border-radius: 50%;
-  text-shadow: none;
-  width: 60px;
-  height: 60px;
-  font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
-  font-size: 42px;
-  font-weight: 700;
-  color: #1e1e1e;
-  text-align: center;
-  line-height: 60px;
-  margin: 0 auto;
-}
-.circle-container .circle.blue {
-  background: #5daced;
-}
-.circle-container .circle.purple {
-  background: #da74f9;
-}
-.circle-container .circle.red {
-  background: #ff6170;
-}
-.circle-container .circle + h4 {
-  margin: 12px 0 0;
-}
-.work-step {
-  border-top: 1px solid #464646;
-  padding: 25px 0;
-}
-.blocky-code table.code td.linenos {
-  border-radius: 0;
-  border: 1px solid #414141;
-  border-right: none;
-  background-color: #323232;
-  padding-left: 20px;
-}
-.blocky-code table.code td.code {
-  border-radius: 0;
-  border: 1px solid #414141;
-  border-left: none;
-  background-color: #323232;
-  padding-left: 10px;
-}
-.lighter-code table.code {
-  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.25);
-}
-.lighter-code table.code td.linenos {
-  background-color: #434343;
-  border: 1px solid #494949;
-  border-right: none;
-  color: #8e8e8e;
-  padding: 12px;
-}
-.lighter-code table.code td.code {
-  border: 1px solid #494949;
-  border-left: none;
-  background-color: #393939;
-}
-@media (max-width: 870px) {
-  .github-corner {
-    display: none;
-  }
-}
-.github-corner:hover .octo-arm {
-  animation: octocat-wave 560ms ease-in-out;
-}
-input#search-input {
-  max-width: 180px;
-  color: #fff;
-  font-weight: 600;
-  border: 0;
-  margin-bottom: 25px;
-  box-sizing: border-box;
-  padding: 10px 15px 10px 35px;
-  background-color: #000;
-  background-size: 15px 15px;
-  background-repeat: no-repeat;
-  background-position: 10px 11px;
-}
-#hits {
-  color: inherit;
-}
-#hits a {
-  font-size: 22px;
-}
-#hits span {
-  color: #ccc;
-  font-weight: 400;
-  font-size: 14px;
-}
-#hits .hit {
-  margin-bottom: 30px;
-}
-#hits hr {
-  margin: 5px 0;
-}
-#hits p {
-  font-weight: 400;
-  margin: 5px 0 0;
-}
-#hits em {
-  background-color: rgba(117, 97, 0, 0.24);
-  color: #ffc900;
-  font-style: normal;
-  font-weight: 700;
-}
-#pagination .ais-pagination--item__disabled {
-  display: none;
-}
-#hits p,
-#pagination .ais-pagination--item__active a {
-  color: #fff;
-}
-#pagination li a {
-  padding: 6px;
-  background: rgba(0, 0, 0, 0.5);
-  border: 1px solid #000;
-  margin: 0 5px;
-}
-#pagination li a:hover {
-  background: rgba(0, 0, 0, 0.2);
-  border-bottom: 1px solid #000;
-}
-.cancel-search {
-  display: inline-block;
-  width: 20px;
-  height: 20px;
-  cursor: pointer;
-  margin-bottom: -4px;
-  opacity: 0.6;
-  margin-right: 4px;
-}
-.cancel-search:hover {
-  opacity: 1;
-}
-.admonition {
-  box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.5);
-  margin: 15px 0;
-  padding: 0 20px;
-  border-radius: 5px;
-  overflow: auto;
-  position: relative;
-}
-.admonition .title {
-  display: block;
-  margin: 0 -20px;
-  padding: 10px 20px 6px 43px;
-  background-repeat: no-repeat;
-  background-position: 20px 55%;
-  background-size: 17px;
-}
-@media (max-width: 870px) {
-  .admonition .title {
-    padding-left: 55px;
-    background-position: 20px 50%;
-  }
-}
-.admonition.note {
-  border-left: 8px solid #448aff;
-  background-color: rgba(68, 138, 255, 0.05);
-}
-.admonition.note .title {
-  background-color: rgba(68, 138, 255, 0.25);
-  border-bottom: 0.1rem solid rgba(68, 138, 255, 0.1);
-  background-position: 20px 50%;
-}
-.admonition.tip {
-  border-left: 8px solid #00bfa5;
-  background-color: rgba(0, 191, 165, 0.05);
-}
-.admonition.tip .title {
-  background-color: rgba(0, 191, 165, 0.25);
-  border-bottom: 0.1rem solid rgba(0, 191, 165, 0.1);
-}
-.admonition.warning {
-  border-left: 8px solid #ff9100;
-  background-color: rgba(255, 145, 0, 0.05);
-}
-.admonition.warning .title {
-  background-color: rgba(255, 145, 0, 0.25);
-  border-bottom: 0.1rem solid rgba(255, 145, 0, 0.1);
-}

+ 0 - 1
docs/rocketsrchrome_files/sun.svg

@@ -1 +0,0 @@
-<svg width="68" height="69" xmlns="http://www.w3.org/2000/svg"><defs><filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="a"><feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowOffsetOuter1" result="shadowMatrixOuter1"/><feMerge><feMergeNode in="shadowMatrixOuter1"/><feMergeNode in="SourceGraphic"/></feMerge></filter></defs><g filter="url(#a)" fill="#FFF" fill-rule="evenodd"><path d="M1.3 33.8h1.2H2l.5.3a.6.6 0 0 0 .1-.3H2l.5.3-.2-.1.2.2-.2-.2.2.2.4-.3c.5-.3 1.3-.5 2.1-.8 1.3-.4 2.8-.8 4-1.3.7-.2 1.2-.4 1.7-.8l.8-.5a2 2 0 0 0 .5-1.4 2.2 2.2 0 0 0-.1-.8l-.8-1.1-1.8-1.8L6 22.8l-1-1a1.6 1.6 0 0 1-.2-.3l-.4.1H5h-.4.4-.6l.6.3a.7.7 0 0 0 0-.3h-.6l.6.3-.5-.2.3.5a.6.6 0 0 0 .2-.3l-.5-.2.3.5-.2-.2.2.2-.2-.2.2.2A1.2 1.2 0 0 1 5 22h.7c.9 0 2 0 3.2.2l3.4.2 1.5-.1.7-.3.7-.6c.3-.4.3-.9.3-1.2 0-.4 0-.8-.2-1.2-.2-.7-.5-1.4-1-2.2l-1.7-3.3a13.8 13.8 0 0 1-.8-2.1l-.4-.1.4.2a.4.4 0 0 0 0-.1l-.4-.1.4.2-.6-.3.5.5a.7.7 0 0 0 0-.2l-.5-.3.5.5-.5-.5.2.6a.6.6 0 0 0 .3-.1l-.5-.5.2.6-.1-.3v.3h.1l-.1-.3v.3l.5.1 1.8.8 3.4 1.8 1.6.7 1.6.4a2 2 0 0 0 1.2-.4c.3-.2.5-.4.6-.7l.3-1 .1-1.2-.2-3.4a33.6 33.6 0 0 1-.2-4.1v-.1l-.2-.2.2.2-.2-.2.2.2-.5-.4.3.6a.6.6 0 0 0 .2-.2l-.5-.4.3.6-.3-.6V5a.7.7 0 0 0 .3 0l-.3-.6V5v-.4.4-.4.4-.2.2-.2.2l.4.3L23.3 7l2.7 3c.4.5.8 1 1.3 1.3l.7.5 1 .2h.4a2 2 0 0 0 .8-.4c.5-.4.7-.8 1-1.2L32 8l1.3-4 .5-1.2.1-.2-.2-.2.2.3-.2-.3.2.3-.3-.6v.6a.6.6 0 0 0 .3 0l-.3-.6v.6V2l-.3.5a.6.6 0 0 0 .3.1V2l-.3.5.2-.2-.2.2.2-.2-.2.2.3.4.8 2.1c.4 1.3.8 2.8 1.3 4l.7 1.7.6.8a2 2 0 0 0 1.4.5l.8-.1 1.1-.8 1.8-1.8 2.5-3 1-1A1.7 1.7 0 0 1 46 5v-.4.4-.4.4-.6l-.3.6a.7.7 0 0 0 .2 0v-.6l-.2.6.2-.5-.5.3.3.2.2-.5-.5.3.2-.1h-.2.2-.2a1.3 1.3 0 0 1 0 .4l.1.8c0 .8 0 2-.2 3l-.2 3.5.1 1.5c0 .2.1.5.3.7.1.3.3.5.6.7a2 2 0 0 0 1.2.4l1.2-.3 2.2-.9 3.3-1.8a13.8 13.8 0 0 1 2.1-.8v-.4.4-.4.4l.2-.6-.5.5a.7.7 0 0 0 .2.1l.3-.6-.5.5.5-.5-.6.2a.6.6 0 0 0 .1.3l.5-.5-.6.2h.3-.4.4-.4a2 2 0 0 1 0 .4l-.8 1.8-1.8 3.4a16.4 16.4 0 0 0-.7 1.6c-.2.5-.4 1-.4 1.6 0 .3 0 .8.4 1.2.2.3.4.5.7.6.3.2.7.3 1 .3l1.2.1 3.4-.2a33.6 33.6 0 0 1 4.1-.2h.1l.2-.2-.3.2h.1l.2-.2-.3.2.5-.5-.6.3a.6.6 0 0 0 .1.2l.5-.5-.6.3.6-.3h-.7v.3l.7-.3h-.7.5-.4.4-.4.1-.1.1-.1l-.4.4-1.5 1.4-3.2 2.7c-.5.4-.9.8-1.2 1.3l-.5.7a2.3 2.3 0 0 0-.3 1v.4l.5.9c.3.4.7.6 1.1.8l2.6 1 4 1.3 1.2.6h.1l.3-.1H65a.3.3 0 0 0 0 .2l.3-.2H65l.6-.2H65a.6.6 0 0 0 0 .3l.6-.3H65h.5l-.5-.3a.6.6 0 0 0 0 .3h.5l-.5-.3.3.2-.2-.2.2.2-.2-.2-.5.3-2 .8c-1.3.4-2.8.8-4 1.3l-1.8.7-.7.6a2 2 0 0 0-.5 1 1.8 1.8 0 0 0 0 .4l.1.8.7 1.1 1.9 1.8 3 2.6a8.7 8.7 0 0 1 1.2 1.2h.4-.4.4-.4.7l-.6-.3a.7.7 0 0 0 0 .2h.6l-.6-.2.5.2-.3-.5a.6.6 0 0 0-.2.3l.5.2-.3-.5.1.2v-.2h-.1l.1.2v-.2l-.4.1h-.8c-.8 0-2 0-3.1-.2l-3.4-.2-1.5.1a3 3 0 0 0-.7.3 2 2 0 0 0-.7.6 2 2 0 0 0-.4 1.2l.2 1.2 1 2.2 1.7 3.3a13.9 13.9 0 0 1 .8 2.1h.5-.4.4-.4l.6.2-.5-.5a.7.7 0 0 0-.1.2l.6.3-.5-.5.5.5-.2-.6a.6.6 0 0 0-.3.1l.5.5-.2-.6v.3-.3.3-.3a2 2 0 0 1-.5-.1l-1.7-.8-3.4-1.8-1.6-.7c-.5-.2-1-.4-1.6-.4a2 2 0 0 0-1.2.4 2 2 0 0 0-.6.7l-.4 1a8 8 0 0 0 0 1.2c0 1 0 2.2.2 3.4a33.6 33.6 0 0 1 .1 4.1v.1l.3.2-.2-.3v.1l.2.2-.2-.3.4.5-.2-.6a.6.6 0 0 0-.2.1l.4.5-.2-.6.2.6v-.6a.7.7 0 0 0-.2 0l.2.6v-.6.4l.1-.4v.4-.4.1-.1.1-.1a2 2 0 0 1-.4-.3l-1.5-1.6-2.6-3.2-1.3-1.2a4.1 4.1 0 0 0-.8-.5 2.3 2.3 0 0 0-1-.2h-.3a2 2 0 0 0-.9.4c-.4.4-.6.7-.8 1.2-.4.7-.7 1.6-1 2.5l-1.3 4-.6 1.2v.1l.1.3-.1-.3.1.3-.1-.3.2.6V65a.6.6 0 0 0-.2 0l.2.6V65v.5l.3-.5a.6.6 0 0 0-.3 0v.5l.3-.5-.1.3.2-.2-.2.2.2-.2-.3-.5c-.3-.4-.5-1.2-.8-2-.4-1.3-.8-2.8-1.3-4-.2-.7-.5-1.3-.8-1.8a3.4 3.4 0 0 0-.5-.7 2 2 0 0 0-1-.5 1.9 1.9 0 0 0-.4 0 2.2 2.2 0 0 0-.8.1l-1.1.7-1.8 1.9-2.6 3a8.7 8.7 0 0 1-1.3 1.3l.1.3v-.4.4-.4.7l.3-.6a.7.7 0 0 0-.3 0v.6l.3-.6-.2.5.4-.3a.6.6 0 0 0-.2-.2l-.2.5.4-.3-.2.1h.3v-.1l-.3.1h.3a1.3 1.3 0 0 1-.1-.4 5.8 5.8 0 0 1 0-.8c0-.8 0-2 .2-3.1l.2-3.4-.1-1.5a3 3 0 0 0-.3-.7 2 2 0 0 0-.6-.7 2 2 0 0 0-1.2-.4l-1.2.3-2.2.9-3.3 1.7a14.3 14.3 0 0 1-2.2.9v.4l.2-.4a.4.4 0 0 0-.2 0v.4l.2-.4-.3.6.5-.5a.7.7 0 0 0-.2-.1l-.3.6.5-.5-.5.5.6-.2a.6.6 0 0 0-.1-.3l-.5.5.6-.2h-.3.3-.3.3a1.9 1.9 0 0 1 .1-.5l.8-1.7 1.8-3.4.7-1.6c.2-.5.3-1 .3-1.6a2 2 0 0 0-.3-1.2 2 2 0 0 0-.7-.6l-1.1-.4a7.8 7.8 0 0 0-1.1 0c-1 0-2.3 0-3.4.2a34.3 34.3 0 0 1-4.2.2l-.2.2.2-.2-.2.2.2-.2-.4.4.6-.2a.6.6 0 0 0-.2-.2l-.4.4.6-.2-.6.2h.6a.7.7 0 0 0 0-.2l-.6.2h.6-.4l.4.1h-.4.4-.2.2-.2.2l.3-.4 1.6-1.5c1-.8 2.2-1.7 3.1-2.6l1.3-1.3.5-.8a2.3 2.3 0 0 0 .2-1v-.3a2 2 0 0 0-.4-.9c-.4-.4-.8-.6-1.2-.8-.7-.4-1.6-.7-2.5-1l-4-1.3-1.2-.6h-.2l-.2.1.3-.1-.3.1.3-.1-.6.2h.6a.6.6 0 0 0 0-.2l-.6.2h.6H0c0 .4.2.8.3 1l.5.6L2 36l2.4 1c1.3.3 2.8.7 3.8 1.1a6.8 6.8 0 0 1 1.4.7l.1-.2-.2.2.2-.2-.2.2.5-.3h-.5a.6.6 0 0 0 0 .3l.5-.3h-.5.5-.5.5-.5.4l-.4-.1h.4-.4.1-.1.1-.1L9 39l-1.6 1.5-3 2.5-1.3 1.3a4 4 0 0 0-.4.7 2.3 2.3 0 0 0-.2 1 1.8 1.8 0 0 0 .8 1.5c.4.3.8.4 1.2.4l1.2.1 3.4-.2a34 34 0 0 1 4.1-.2h.1l.1-.2-.1.2.1-.2-.1.2.3-.4-.4.3a.6.6 0 0 0 0 .1l.4-.4-.4.3.4-.3-.5.1v.2l.5-.3-.5.1h.2-.2.2-.2l-.1.5-.8 1.8-1.8 3.3-.7 1.6c-.2.6-.3 1-.3 1.6v.7a1.8 1.8 0 0 0 1.2 1.2l.7.1c.5 0 .9 0 1.3-.2a15 15 0 0 0 2.1-1l3.4-1.7a13.9 13.9 0 0 1 2-.8h.1V54l-.2.4a.5.5 0 0 0 .2.1V54l-.2.4.3-.4-.5.3a.5.5 0 0 0 .2.1l.3-.4-.5.3.1.3v.7c0 .9 0 2-.2 3.1l-.2 3.4.1 1.7.4.8.8.7.7.1.9-.1 1-.8c.7-.5 1.2-1.1 1.8-1.8 1-1 1.8-2.2 2.6-3.1a8.7 8.7 0 0 1 1.3-1.2v-.3.3-.3.3-.6l-.2.6h.1v-.6l-.1.6.1-.5-.3.4.2.1.1-.5-.3.4.3.5.8 2.2c.4 1.3.8 2.8 1.3 4 .2.7.5 1.3.8 1.8l.7.7c.3.2.7.3 1.1.3a2 2 0 0 0 1-.2l.6-.5.7-1.2 1-2.4a25 25 0 0 1 1.1-3.8l.6-1.2a1 1 0 0 1 0-.2v-.2.3-.3.3l-.2-.6v.6a.6.6 0 0 0 .2 0l-.2-.6v.6-.6.6-.6.6-.4l-.1.4v-.4.4-.1.1-.1.1l.5.4 1.5 1.6 2.5 3 1.3 1.3.8.5 1 .2a1.8 1.8 0 0 0 1.5-.8l.4-1.2.1-1.3-.2-3.4a33.2 33.2 0 0 1-.2-4v-.1l-.2-.2.2.2-.2-.2.2.2-.4-.4.3.5a.6.6 0 0 0 .1 0l-.4-.5.3.5-.3-.4.1.5a.6.6 0 0 0 .2 0l-.3-.5.1.5v-.3.3-.3.3l.5.1 1.7.8 3.4 1.8 1.6.7c.6.2 1 .3 1.6.3h.7a1.8 1.8 0 0 0 .8-.5l.4-.8.1-.7c0-.4 0-.8-.2-1.2-.2-.7-.5-1.4-1-2.1l-1.7-3.4a14 14 0 0 1-.8-2.1h-.1.1-.1.1-.5l.4.2a.5.5 0 0 0 .1-.2h-.5l.4.2-.4-.3.3.5a.5.5 0 0 0 .1-.2l-.4-.3.3.5.3-.1a5.7 5.7 0 0 1 .7 0c.8 0 2 0 3.1.2l3.4.2c.6 0 1.1 0 1.7-.2l.8-.3.7-.9a1.8 1.8 0 0 0 .1-.7 2.2 2.2 0 0 0-.2-.8c-.1-.4-.4-.8-.7-1a7.7 7.7 0 0 0-1.8-1.8c-1-1-2.2-1.8-3.1-2.6l-1-1a1.7 1.7 0 0 1-.2-.3h-.3.3-.3.3-.6l.6.2v-.1h-.6.6-.5l.4.3a.5.5 0 0 0 .1-.2l-.5-.1.4.3.5-.3c.5-.3 1.3-.5 2.2-.8 1.3-.4 2.8-.8 4-1.3a8 8 0 0 0 1.7-.9l.8-.6c.2-.3.3-.7.3-1.2a1.9 1.9 0 0 0-.2-1 2.5 2.5 0 0 0-.6-.5 5 5 0 0 0-1.1-.7l-2.4-1-3.8-1.1-1.2-.6a1 1 0 0 1-.2-.1l-.2.2.2-.2-.2.2.2-.2-.5.3h.6a.6.6 0 0 0 0-.3l-.6.3h.6-.6.6-.6.6-.4l.4.1h-.4.4-.1.1-.1.1l.4-.5 1.6-1.5 3-2.6c.5-.4 1-.8 1.3-1.3l.5-.7.2-1-.1-.7a1.9 1.9 0 0 0-.7-.8 3 3 0 0 0-1.2-.4 7.7 7.7 0 0 0-1.3-.1l-3.4.2a33.2 33.2 0 0 1-4 .2h-.1l-.2.2.2-.2-.2.2.2-.2-.4.4.5-.3a.6.6 0 0 0-.1-.1l-.4.4.5-.3-.4.3.5-.1a.6.6 0 0 0 0-.2l-.5.3.5-.1h-.3.3-.3.3a2 2 0 0 1 .1-.5l.8-1.8 1.8-3.3.7-1.6c.2-.6.3-1 .3-1.6v-.8a1.8 1.8 0 0 0-.5-.7 1.9 1.9 0 0 0-.8-.4 2.3 2.3 0 0 0-.7-.1c-.4 0-.8 0-1.2.2-.7.2-1.4.5-2.2 1l-3.3 1.7a14 14 0 0 1-2.1.8l-.1.5.3-.4a.5.5 0 0 0-.2-.1l-.1.5.3-.4-.3.4.4-.3a.5.5 0 0 0-.1-.1l-.3.4.4-.3a1.4 1.4 0 0 1 0-.3 5.7 5.7 0 0 1 0-.7c0-.9 0-2 .2-3.2L48 6c0-.6 0-1.2-.2-1.7a2.7 2.7 0 0 0-.3-.8 1.9 1.9 0 0 0-.9-.7 1.8 1.8 0 0 0-.7-.1 2.2 2.2 0 0 0-.8.1l-1.1.8-1.8 1.8c-.8 1-1.7 2.2-2.5 3l-1 1a1.7 1.7 0 0 1-.3.3v.3-.3.3-.3.6l.2-.6h-.1v.6-.6.4l.3-.3a.5.5 0 0 0-.2-.1l-.1.4.3-.3-.3-.5c-.3-.5-.5-1.3-.8-2.2-.4-1.3-.8-2.8-1.3-4a8 8 0 0 0-.9-1.8 3 3 0 0 0-.6-.7 2 2 0 0 0-1.2-.4l-1 .3-.5.5a5 5 0 0 0-.8 1.2l-.9 2.4-1.1 3.8-.6 1.2a1 1 0 0 1-.1.2l.2.2-.2-.3.2.3-.2-.3.3.6-.1-.6a.6.6 0 0 0-.2 0l.3.6-.1-.6.1.5v-.5.5-.5.4l.1-.4v.4-.4.1-.1.1-.1a2.5 2.5 0 0 1-.5-.4l-1.5-1.6-2.6-3a4 4 0 0 0-1.3-1.3 4 4 0 0 0-.7-.5 2.3 2.3 0 0 0-1-.2l-.7.1a1.9 1.9 0 0 0-.8.7 3 3 0 0 0-.4 1.2 7.8 7.8 0 0 0-.1 1.3c0 1 0 2.2.2 3.3a33.6 33.6 0 0 1 .2 4.1v.1l.2.1-.2-.1.2.1-.2-.1.4.3-.3-.4a.6.6 0 0 0-.1 0l.4.4-.3-.4.3.4-.1-.5a.6.6 0 0 0-.2 0l.3.5-.1-.5v.2-.2.2-.2a2 2 0 0 1-.5-.1l-1.8-.8-3.3-1.8a16.4 16.4 0 0 0-1.7-.7c-.5-.2-1-.3-1.6-.3h-.7l-.7.5a1.8 1.8 0 0 0-.4.7 2.2 2.2 0 0 0-.1.8c0 .4 0 .8.2 1.2l.9 2.1 1.8 3.4a14 14 0 0 1 .8 2.1h.5l-.4-.2a.5.5 0 0 0-.1.2h.5l-.4-.2.4.3-.3-.5a.5.5 0 0 0-.1.2l.4.3-.3-.5-.3.1h-.7c-.9 0-2 0-3.2-.2l-3.4-.2-1.6.1a2.7 2.7 0 0 0-.8.4 1.9 1.9 0 0 0-.7.8 1.8 1.8 0 0 0-.1.7l.1.9.8 1c.5.7 1.1 1.2 1.8 1.8 1 1 2.2 1.8 3 2.6a8.6 8.6 0 0 1 1.3 1.3h.3-.3.3-.3.5l-.5-.2v.1h.5-.5.4l-.3-.3a.5.5 0 0 0-.1.2l.4.1-.3-.3-.5.3-2.2.8c-1.3.4-2.8.8-4 1.3A8 8 0 0 0 1 32a3 3 0 0 0-.7.7 2 2 0 0 0-.4 1.1h1.3"/><path d="M16.3 33.8h1.2a16.2 16.2 0 0 1 4.8-11.4 16.2 16.2 0 0 1 11.4-4.8 16 16 0 0 1 11.5 4.8A16.2 16.2 0 0 1 50 33.8c0 4.5-1.9 8.6-4.8 11.5a16.2 16.2 0 0 1-11.5 4.8 16.2 16.2 0 0 1-11.4-4.8 16.2 16.2 0 0 1-4.8-11.5H15a18.7 18.7 0 1 0 37.4 0 18.7 18.7 0 0 0-37.4 0h1.3"/></g></svg>

+ 0 - 1
docs/rocketsrchrome_files/telescope.svg

@@ -1 +0,0 @@
-<svg width="71" height="62" xmlns="http://www.w3.org/2000/svg"><defs><filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="a"><feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowOffsetOuter1" result="shadowMatrixOuter1"/><feMerge><feMergeNode in="shadowMatrixOuter1"/><feMergeNode in="SourceGraphic"/></feMerge></filter></defs><g filter="url(#a)" fill="#FFF" fill-rule="evenodd"><path d="M69.102 15.534l-.176-1.251-17.997 2.504-1.604-11.455 16.742-2.33 1.78 12.707 1.255-.175-.176-1.251.176 1.251 1.256-.174L68.228.15 46.463 3.178l2.305 16.461 21.765-3.029-.175-1.251-1.256.174"/><path d="M48.858 15.387l-.175-1.252-15.082 2.099-.708-5.057 13.825-1.925.884 6.31 1.256-.175-.175-1.252.175 1.252 1.256-.175-1.236-8.813-18.847 2.623 1.41 10.065 18.849-2.623-.176-1.252-1.256.175"/><path d="M33.104 17.58l-.175-1.253-22.666 3.155-.708-5.058 21.41-2.98.884 6.31 1.255-.175-.175-1.252.175 1.252 1.256-.175-1.234-8.812L6.692 12.27l1.41 10.064 26.433-3.678-.175-1.252-1.256.175"/><path d="M9.345 22.071L9.17 20.82l-4.58.637-1.033-7.384 3.322-.462 1.21 8.635 1.256-.175-.175-1.251.175 1.251 1.256-.175-1.56-11.138-8.346 1.161L2.43 24.31l8.347-1.16-.176-1.253-1.256.175m17.914-3.115v39.81c0 .7.567 1.265 1.268 1.265.7 0 1.268-.566 1.268-1.264v-39.81c0-.699-.568-1.264-1.268-1.264-.7 0-1.268.565-1.268 1.263m-3.804 0v39.81c0 .7.568 1.265 1.268 1.265.7 0 1.268-.566 1.268-1.264v-39.81c0-.699-.567-1.264-1.268-1.264-.7 0-1.268.565-1.268 1.263"/><path d="M24.723 60.032h3.804c.7 0 1.268-.566 1.268-1.264 0-.698-.568-1.264-1.268-1.264h-3.804c-.7 0-1.268.566-1.268 1.264 0 .698.568 1.264 1.268 1.264m3.607-31.537l22.559 22.487a1.271 1.271 0 0 0 1.793 0 1.261 1.261 0 0 0 0-1.788L30.123 26.707a1.271 1.271 0 0 0-1.793 0 1.261 1.261 0 0 0 0 1.788m-.144 4.84l20.57 20.504a1.27 1.27 0 0 0 1.792 0 1.26 1.26 0 0 0 0-1.787L29.98 31.548a1.27 1.27 0 0 0-1.793 0 1.26 1.26 0 0 0 0 1.787"/><path d="M50.548 53.839l2.5-2.491a1.261 1.261 0 0 0 0-1.788 1.271 1.271 0 0 0-1.793 0l-2.5 2.492a1.26 1.26 0 0 0 0 1.787 1.27 1.27 0 0 0 1.793 0M23.696 26.707L1.136 49.194a1.261 1.261 0 0 0 0 1.788 1.27 1.27 0 0 0 1.793 0l22.56-22.487a1.261 1.261 0 0 0 0-1.788 1.27 1.27 0 0 0-1.793 0m.142 4.841L3.27 52.052a1.26 1.26 0 0 0 0 1.787 1.271 1.271 0 0 0 1.793 0l20.568-20.504a1.26 1.26 0 0 0 0-1.787 1.271 1.271 0 0 0-1.793 0"/><path d="M5.063 52.052l-2.5-2.492a1.27 1.27 0 0 0-1.793 0 1.261 1.261 0 0 0 0 1.788l2.5 2.491a1.271 1.271 0 0 0 1.793 0 1.26 1.26 0 0 0 0-1.787"/></g></svg>

+ 0 - 1
docs/rocketsrchrome_files/templating-icon.svg

@@ -1 +0,0 @@
-<svg width="101" height="52" xmlns="http://www.w3.org/2000/svg"><g fill="#FFF" fill-rule="evenodd"><path d="M37.102 50.632V26h10.306v-2.737H34.354v27.369h2.748"/><path d="M28.857 52H42.6v-2.737H28.857zm0-4.79H42.6v-2.736H28.857zm39.163 3.422V23.263H54.966V26h10.306v24.632h2.748"/><path d="M59.776 52h13.741v-2.737H59.776zm0-4.79h13.741v-2.736H59.776zM39.163 13h22.674a1.37 1.37 0 0 0 1.374-1.368 1.37 1.37 0 0 0-1.374-1.369H39.163a1.37 1.37 0 0 0-1.374 1.369A1.37 1.37 0 0 0 39.163 13"/><path d="M99.626 15.737v-1.369H63.21v-4.79h35.04v6.159h1.375v-1.369 1.369H101V6.842H60.463v10.263H101v-1.368h-1.374m-60.463-.684v-1.369H2.748v-4.79H37.79v6.159h1.374v-1.369 1.369h1.374V6.158H0V16.42h40.537v-1.368h-1.374"/><path d="M9.619 7.526v6.842a1.37 1.37 0 0 0 1.374 1.369 1.37 1.37 0 0 0 1.374-1.369V7.526a1.37 1.37 0 0 0-1.374-1.368A1.37 1.37 0 0 0 9.62 7.526m15.115 0v6.842a1.37 1.37 0 0 0 1.374 1.369 1.37 1.37 0 0 0 1.374-1.369V7.526a1.37 1.37 0 0 0-1.374-1.368 1.37 1.37 0 0 0-1.374 1.368m63.898 1.369v6.842a1.37 1.37 0 0 0 1.374 1.368 1.37 1.37 0 0 0 1.374-1.368V8.895a1.37 1.37 0 0 0-1.374-1.369 1.37 1.37 0 0 0-1.374 1.369m-15.116 0v6.842a1.37 1.37 0 0 0 1.374 1.368 1.37 1.37 0 0 0 1.374-1.368V8.895a1.37 1.37 0 0 0-1.374-1.369 1.37 1.37 0 0 0-1.374 1.369M55.653 34.21v-1.368h-7.558V2.737h6.184V34.21h1.374v-1.369 1.369h1.374V0h-11.68v35.579h11.68V34.21h-1.374"/></g></svg>

+ 0 - 1
docs/rocketsrchrome_files/testing-icon.svg

@@ -1 +0,0 @@
-<svg width="47" height="54" xmlns="http://www.w3.org/2000/svg"><g fill="#FFF" fill-rule="evenodd"><path d="M38.339 48h-1.08c-.004.12-.029.224-.157.407-.113.155-.314.35-.61.55-.515.352-1.31.71-2.296 1.018-1.48.465-3.389.83-5.498 1.07-2.11.242-4.425.364-6.739.364-4.027.002-8.065-.374-11.006-1.094-1.468-.356-2.662-.808-3.395-1.273-.368-.23-.613-.457-.74-.635-.13-.183-.154-.287-.157-.407a7.28 7.28 0 0 1 1.122-3.897c1.09-1.764 2.98-3.27 5.442-4.328 2.458-1.058 5.473-1.66 8.734-1.66 4.35-.003 8.258 1.075 10.998 2.86 1.371.89 2.45 1.952 3.179 3.128A7.286 7.286 0 0 1 37.259 48h2.16a9.492 9.492 0 0 0-1.452-5.055c-1.395-2.245-3.66-3.987-6.426-5.178-2.77-1.19-6.058-1.833-9.582-1.834-4.697.003-8.978 1.14-12.166 3.207-1.593 1.035-2.913 2.31-3.841 3.805A9.482 9.482 0 0 0 4.5 48c-.004.63.228 1.23.579 1.702.307.42.697.763 1.143 1.066.782.527 1.744.938 2.86 1.29 1.67.524 3.69.901 5.895 1.155 2.205.252 4.593.378 6.982.378 4.163-.002 8.314-.376 11.515-1.156 1.604-.394 2.97-.88 4.028-1.54.528-.333.986-.714 1.338-1.192A2.878 2.878 0 0 0 39.42 48h-1.081"/><path d="M23.394 37.09V36h-2.702V2.182h1.621V37.09h1.08V36v1.09h1.081V0h-5.942v38.182h5.942V37.09h-1.08"/><path d="M45.543 16.003l.496-.969c-1.65-.864-3.33-1.182-4.953-1.18-2.222.003-4.346.566-6.41 1.092-2.066.53-4.07 1.027-6.015 1.024-1.426-.001-2.819-.254-4.26-.95l-.467.983h1.08V2.913h-1.08l-.467.983c1.755.853 3.51 1.167 5.194 1.165 2.304-.002 4.477-.564 6.545-1.091 2.069-.533 4.032-1.028 5.88-1.025 1.354.002 2.643.25 3.961.936l.496-.969h-1.08v13.091h1.08l.496-.969-.496.97h1.08V2.247l-.584-.305c-1.65-.864-3.33-1.182-4.953-1.18-2.222.003-4.346.566-6.41 1.092-2.066.53-4.07 1.027-6.015 1.024-1.426-.001-2.819-.254-4.26-.95l-1.548-.75V16.69l.614.297c1.755.853 3.51 1.167 5.194 1.165 2.304-.003 4.477-.564 6.545-1.091 2.069-.533 4.032-1.028 5.88-1.025 1.354.002 2.643.25 3.961.936l1.576.823v-1.792h-1.08M5.157 14.22l.741.33.029-.055v-.001l-.198-.146.128.206a.244.244 0 0 0 .07-.06l-.198-.146.128.206-.264-.427v.5c.11.001.21-.038.264-.073l-.264-.427v.5-.46l-.315.348a.479.479 0 0 0 .315.112v-.46l-.315.348.133-.147-.151.129.018.018.133-.147-.151.129.029-.025-.03.022v.003l.03-.025-.03.022.028.057.643 1.471c.192.435.51.762.873.996.366.231.788.377 1.25.38.071 0 .143-.005.216-.012l1.583-.174.05-.003h.014l.023-.199-.073.184.05.015.023-.199-.073.184.175-.44-.38.271a.479.479 0 0 0 .205.17l.175-.442-.38.272.412-.295h-.509c-.002.075.027.2.097.295l.412-.295h-.509.277l-.26-.106a.276.276 0 0 0-.017.106h.277l-.26-.106-.006.011-.029.042-.94 1.298a2.33 2.33 0 0 0-.42 1.364c.002.468.122.946.42 1.363L9.546 22l.029.042.005.012.121-.055-.128.031.007.024.121-.055-.128.031.343-.083h-.351l.008.083.343-.083h-.351.498l-.445-.223a.508.508 0 0 0-.053.223h.498l-.445-.223.437.22-.204-.455a.508.508 0 0 0-.233.235l.437.22-.204-.455.109.242-.048-.262-.06.02.108.242-.048-.262.006.037-.003-.038-.003.001.006.037-.003-.038h-.013l-.05-.002-1.583-.174a1.946 1.946 0 0 0-.217-.012 2.35 2.35 0 0 0-1.249.379c-.363.234-.68.56-.873.996l-.643 1.472-.028.055-.001.002.198.145-.127-.206c-.056.036-.07.06-.071.06l.198.146-.127-.206.264.428v-.5a.506.506 0 0 0-.264.072l.264.428v-.5.458l.315-.346a.475.475 0 0 0-.315-.112v.458l.315-.346-.133.146.15-.128-.017-.018-.133.146.15-.128-.028.025.03-.023-.001-.002-.03.025.032-.023-.03-.056-.642-1.472a2.29 2.29 0 0 0-.873-.996 2.349 2.349 0 0 0-1.25-.38c-.071 0-.143.005-.216.013l-1.584.174-.05.003-.013-.001-.024.2.073-.185-.05-.015-.023.2.073-.185-.174.441.379-.272a.476.476 0 0 0-.205-.17l-.174.442.379-.272-.412.295h.509a.528.528 0 0 0-.097-.295l-.412.295h.509-.277l.261.107a.305.305 0 0 0 .016-.107h-.277l.261.107.006-.012.028-.042.94-1.298c.299-.417.418-.895.42-1.363a2.33 2.33 0 0 0-.42-1.364l-.972-1.342.032.044-.028-.042-.007-.012-.12.055.128-.032-.008-.023-.12.055.128-.032-.343.084h.352l-.009-.084-.343.084h.352-.499l.445.223a.52.52 0 0 0 .054-.223h-.499l.445.223-.437-.22.204.455a.511.511 0 0 0 .233-.235l-.437-.22.204.455-.108-.242.048.263.06-.021-.108-.242.048.263-.007-.038.003.038h.004l-.007-.038.003.038h.014l.049.003 1.584.174c.073.007.145.011.216.011a2.351 2.351 0 0 0 1.25-.379c.363-.234.68-.56.873-.996l.642-1.471-.741-.33-.742-.33-.642 1.47a.678.678 0 0 1-.257.274.752.752 0 0 1-.383.126l-.04-.002-1.585-.174a2.069 2.069 0 0 0-.224-.013 1.38 1.38 0 0 0-.827.248 1.115 1.115 0 0 0-.457.91c.006.38.153.662.331.914l.94 1.297c.054.068.11.228.108.398a.705.705 0 0 1-.107.397l-.94 1.297c-.18.252-.326.534-.332.914a1.124 1.124 0 0 0 .665 1.032c.213.097.419.125.619.126.075 0 .15-.004.224-.013l1.584-.174.041-.002a.755.755 0 0 1 .383.126c.132.083.227.2.257.273l.642 1.472c.094.212.213.409.398.582.18.17.461.32.78.318.318.001.6-.147.779-.318.186-.173.305-.37.398-.582l.643-1.472a.678.678 0 0 1 .256-.273.757.757 0 0 1 .383-.126l.042.002 1.583.174c.075.009.15.013.225.013.263-.002.55-.05.827-.248a1.109 1.109 0 0 0 .456-.91c-.006-.38-.152-.661-.33-.913l-.941-1.298a.706.706 0 0 1-.107-.397.706.706 0 0 1 .107-.398l.958-1.32-.017.022c.178-.251.324-.533.33-.913a1.13 1.13 0 0 0-.116-.505 1.126 1.126 0 0 0-.549-.527 1.476 1.476 0 0 0-.618-.126c-.076 0-.15.005-.225.013l-1.583.174-.042.002a.752.752 0 0 1-.383-.126.678.678 0 0 1-.256-.273L6.77 13.89a1.715 1.715 0 0 0-.397-.583 1.15 1.15 0 0 0-.78-.317 1.15 1.15 0 0 0-.78.317c-.185.173-.304.37-.398.583l.742.33"/></g></svg>

+ 35 - 35
notes/Parity.md

@@ -2,41 +2,41 @@
 
 Sorted by priority
 
-| Feature                | Dioxus | React | Notes                                |
-| ---------------------- | ------ | ----- | ------------------------------------ |
-| ----- Phase 1 -----    | -----  | ----- | -----                                |
-| Conditional Rendering  | ✅     | ✅    | if/then to hide/show component       |
-| Map, Iterator          | ✅     | ✅    | map/filter/reduce rsx!               |
-| Keyed Components       | ✅     | ✅    | advanced diffing with keys           |
-| Web                    | ✅     | ✅    | renderer for web browser             |
-| Desktop (webview)      | ✅     | ✅    | renderer for desktop                 |
-| Context                | ✅     | ✅    | share state through the tree         |
-| Hook                   | ✅     | ✅    | memory cells in components           |
-| SSR                    | ✅     | ✅    | render directly to string            |
-| Runs natively          | ✅     | 👀    | runs as a sharable binary            |
-| Null components        | 👀     | ✅    | allow returning None                 |
-| Fragments              | 👀     | ✅    | no requirement on main root          |
-| Component Children     | 👀     | ✅    | ctx.children() as a list of nodes    |
-| NodeRef                | 👀     | ✅    | gain direct access to nodes          |
-| Controlled Inputs      | 👀     | ✅    | stateful wrappers around inputs      |
-| No-div components      | 👀     | ✅    | components that render components    |
-| CSS/Inline Styles      | 🛠      | ✅    | syntax for inline/conditional styles |
-| 1st class global state | 🛠      | ✅    | redux/recoil/mobx on top of context  |
-| ----- Phase 2 -----    | -----  | ----- | -----                                |
-| 1st class router       | 👀     | ✅    | Hook built on top of history         |
-| Assets                 | 👀     | ✅    | include css/svg/img url statically   |
-| Integrated classnames  | 🛠      | 👀    | built-in `classnames`                |
-| Suspense               | 👀     | 👀    | schedule future render from future   |
-| Transition             | 👀     | 👀    | High-level control over suspense     |
-| Animation              | 👀     | ✅    | Spring-style animations              |
-| Mobile                 | 👀     | ✅    | Render with cacao                    |
-| Desktop (native)       | 👀     | ✅    | Render with native desktop           |
-| 3D Renderer            | 👀     | ✅    | react-three-fiber                    |
-| ----- Phase 3 -----    | -----  | ----- | -----                                |
-| Portal                 | 👀     | ✅    | cast elements through tree           |
-| Error/Panic boundary   | 👀     | ✅    | catch panics and display BSOD        |
-| Code-splitting         | 👀     | ✅    | Make bundle smaller/lazy             |
-| LiveView               | 👀     | 👀    | Example for SSR + WASM apps          |
+| Feature                | Dioxus | React | Notes                                            |
+| ---------------------- | ------ | ----- | ------------------------------------------------ |
+| ----- Phase 1 -----    | -----  | ----- | -----                                            |
+| Conditional Rendering  | ✅     | ✅    | if/then to hide/show component                   |
+| Map, Iterator          | ✅     | ✅    | map/filter/reduce rsx!                           |
+| Keyed Components       | ✅     | ✅    | advanced diffing with keys                       |
+| Web                    | ✅     | ✅    | renderer for web browser                         |
+| Desktop (webview)      | ✅     | ✅    | renderer for desktop                             |
+| Context                | ✅     | ✅    | share state through the tree                     |
+| Hook                   | ✅     | ✅    | memory cells in components                       |
+| SSR                    | ✅     | ✅    | render directly to string                        |
+| Runs natively          | ✅     | 👀    | runs as a sharable binary                        |
+| Component Children     | ✅     | ✅    | ctx.children() as a list of nodes                |
+| Null components        | ✅     | ✅    | allow returning no components                    |
+| No-div components      | ✅     | ✅    | components that render components                |
+| Fragments              | ✅     | ✅    | rsx! can return multiple elements without a root |
+| NodeRef                | 👀     | ✅    | gain direct access to nodes                      |
+| Controlled Inputs      | 👀     | ✅    | stateful wrappers around inputs                  |
+| CSS/Inline Styles      | 🛠      | ✅    | syntax for inline/conditional styles             |
+| 1st class global state | 🛠      | ✅    | redux/recoil/mobx on top of context              |
+| ----- Phase 2 -----    | -----  | ----- | -----                                            |
+| 1st class router       | 👀     | ✅    | Hook built on top of history                     |
+| Assets                 | 👀     | ✅    | include css/svg/img url statically               |
+| Integrated classnames  | 🛠      | 👀    | built-in `classnames`                            |
+| Suspense               | 👀     | 👀    | schedule future render from future               |
+| Transition             | 👀     | 👀    | High-level control over suspense                 |
+| Animation              | 👀     | ✅    | Spring-style animations                          |
+| Mobile                 | 👀     | ✅    | Render with cacao                                |
+| Desktop (native)       | 👀     | ✅    | Render with native desktop                       |
+| 3D Renderer            | 👀     | ✅    | react-three-fiber                                |
+| ----- Phase 3 -----    | -----  | ----- | -----                                            |
+| Portal                 | 👀     | ✅    | cast elements through tree                       |
+| Error/Panic boundary   | 👀     | ✅    | catch panics and display BSOD                    |
+| Code-splitting         | 👀     | ✅    | Make bundle smaller/lazy                         |
+| LiveView               | 👀     | 👀    | Example for SSR + WASM apps                      |
 
 ## Required services:
 

+ 2 - 1
packages/core-macro/examples/prop_test.rs

@@ -2,8 +2,9 @@ fn main() {}
 
 pub mod dioxus {
     pub mod prelude {
-        pub trait Properties {
+        pub unsafe trait Properties {
             type Builder;
+            const CAN_BE_MEMOIZED: bool;
             fn builder() -> Self::Builder;
         }
     }

+ 2 - 1
packages/core-macro/src/props/mod.rs

@@ -679,8 +679,9 @@ Finally, call `.build()` to create the instance of `{name}`.
                     }
                 }
 
-                impl #impl_generics dioxus::prelude::Properties for #name #ty_generics{
+                unsafe impl #impl_generics dioxus::prelude::Properties for #name #ty_generics{
                     type Builder = #builder_name #generics_with_empty;
+                    const CAN_BE_MEMOIZED: bool = true;
                     fn builder() -> Self::Builder {
                         #name::builder()
                     }

+ 5 - 6
packages/core-macro/src/rsx/ambiguous.rs

@@ -50,14 +50,13 @@ impl Parse for AmbiguousElement {
                 false => {
                     let first_char = name_str.chars().next().unwrap();
                     if first_char.is_ascii_uppercase() {
-                        if name_str == "Fragment" {
-                            input
+                        match name_str.as_str() {
+                            "Fragment" => input
                                 .parse::<Fragment>()
-                                .map(|c| AmbiguousElement::Fragment(c))
-                        } else {
-                            input
+                                .map(|c| AmbiguousElement::Fragment(c)),
+                            _ => input
                                 .parse::<Component>()
-                                .map(|c| AmbiguousElement::Component(c))
+                                .map(|c| AmbiguousElement::Component(c)),
                         }
                     } else {
                         let name = input.parse::<Ident>().unwrap();

+ 25 - 11
packages/core-macro/src/rsx/component.rs

@@ -26,7 +26,7 @@ pub struct Component {
     // accept any path-like argument
     name: syn::Path,
     body: Vec<ComponentField>,
-    _children: Vec<Node>,
+    children: Vec<Node>,
 }
 
 impl Parse for Component {
@@ -41,7 +41,7 @@ impl Parse for Component {
         syn::braced!(content in s);
 
         let mut body: Vec<ComponentField> = Vec::new();
-        let _children: Vec<Node> = Vec::new();
+        let mut children: Vec<Node> = Vec::new();
 
         'parsing: loop {
             // [1] Break if empty
@@ -49,7 +49,7 @@ impl Parse for Component {
                 break 'parsing;
             }
 
-            if content.peek(token::Brace) {
+            if content.peek(token::Brace) && content.peek2(Token![...]) {
                 let inner: ParseBuffer;
                 syn::braced!(inner in content);
                 if inner.peek(Token![...]) {
@@ -57,7 +57,11 @@ impl Parse for Component {
                 }
             }
 
-            body.push(content.parse::<ComponentField>()?);
+            if content.peek(Ident) && content.peek2(Token![:]) {
+                body.push(content.parse::<ComponentField>()?);
+            } else {
+                children.push(content.parse::<Node>()?);
+            }
 
             // consume comma if it exists
             // we don't actually care if there *are* commas between attrs
@@ -66,13 +70,10 @@ impl Parse for Component {
             }
         }
 
-        // todo: add support for children
-        let children: Vec<Node> = vec![];
-
         Ok(Self {
             name,
             body,
-            _children: children,
+            children,
         })
     }
 }
@@ -109,9 +110,22 @@ impl ToTokens for Component {
             None => quote! {None},
         };
 
-        let _toks = tokens.append_all(quote! {
-            dioxus::builder::virtual_child(__ctx, #name, #builder, #key_token)
-        });
+        let childs = &self.children;
+        let children = quote! {
+            ChildrenList::new(__ctx)
+                #( .add_child(#childs) )*
+                .finish()
+        };
+
+        tokens.append_all(quote! {
+            dioxus::builder::virtual_child(
+                __ctx,
+                #name,
+                #builder,
+                #key_token,
+                #children
+            )
+        })
     }
 }
 

+ 20 - 8
packages/core-macro/src/rsx/element.rs

@@ -133,6 +133,10 @@ impl Parse for ElementAttr {
             }
         } else {
             match name_str.as_str() {
+                "key" => {
+                    // todo: better error here
+                    AttrType::BumpText(s.parse::<LitStr>()?)
+                }
                 "style" => {
                     //
                     todo!("inline style not yet supported")
@@ -196,10 +200,23 @@ impl ToTokens for ElementAttr {
         let name = self.name.to_string();
         let nameident = &self.name;
         let _attr_stream = TokenStream2::new();
+
         match &self.ty {
-            AttrType::BumpText(value) => {
+            AttrType::BumpText(value) => match name.as_str() {
+                "key" => {
+                    tokens.append_all(quote! {
+                        .key2(format_args_f!(#value))
+                    });
+                }
+                _ => {
+                    tokens.append_all(quote! {
+                        .attr(#name, format_args_f!(#value))
+                    });
+                }
+            },
+            AttrType::FieldTokens(exp) => {
                 tokens.append_all(quote! {
-                    .attr(#name, format_args_f!(#value))
+                    .attr(#name, #exp)
                 });
             }
             AttrType::Event(event) => {
@@ -207,16 +224,11 @@ impl ToTokens for ElementAttr {
                     .add_listener(dioxus::events::on::#nameident(__ctx, #event))
                 });
             }
-            AttrType::FieldTokens(exp) => {
-                tokens.append_all(quote! {
-                    .attr(#name, #exp)
-                });
-            }
             AttrType::EventTokens(event) => {
                 //
                 tokens.append_all(quote! {
                     .add_listener(dioxus::events::on::#nameident(__ctx, #event))
-                })
+                });
             }
         }
     }

+ 36 - 3
packages/core-macro/src/rsx/fragment.rs

@@ -8,6 +8,10 @@
 //! - [ ] Children
 //! - [ ] Keys
 
+use syn::parse::ParseBuffer;
+
+use super::AmbiguousElement;
+
 use {
     proc_macro::TokenStream,
     proc_macro2::{Span, TokenStream as TokenStream2},
@@ -19,15 +23,44 @@ use {
     },
 };
 
-pub struct Fragment {}
+pub struct Fragment {
+    children: Vec<AmbiguousElement>,
+}
 impl Parse for Fragment {
     fn parse(input: ParseStream) -> Result<Self> {
-        todo!()
+        input.parse::<Ident>()?;
+
+        let children = Vec::new();
+
+        // parse the guts
+        let content: ParseBuffer;
+        syn::braced!(content in input);
+        while !content.is_empty() {
+            content.parse::<AmbiguousElement>()?;
+
+            if content.peek(Token![,]) {
+                let _ = content.parse::<Token![,]>();
+            }
+        }
+        Ok(Self { children })
     }
 }
 
 impl ToTokens for Fragment {
     fn to_tokens(&self, tokens: &mut TokenStream2) {
-        todo!()
+        let childs = &self.children;
+        let children = quote! {
+            ChildrenList::new(__ctx)
+                #( .add_child(#childs) )*
+                .finish()
+        };
+        tokens.append_all(quote! {
+            // #key_token,
+            dioxus::builder::vfragment(
+                __ctx,
+                None,
+                #children
+            )
+        })
     }
 }

+ 39 - 28
packages/core-macro/src/rsx/mod.rs

@@ -26,7 +26,7 @@ pub use node::*;
 
 use crate::util::is_valid_tag;
 use proc_macro2::TokenStream as TokenStream2;
-use quote::{quote, ToTokens};
+use quote::{quote, ToTokens, TokenStreamExt};
 use syn::{
     parse::{Parse, ParseStream},
     Error, Ident, LitStr, Result, Token,
@@ -34,7 +34,7 @@ use syn::{
 
 pub struct RsxRender {
     custom_context: Option<Ident>,
-    root: AmbiguousElement,
+    roots: Vec<AmbiguousElement>,
 }
 
 impl Parse for RsxRender {
@@ -61,16 +61,13 @@ impl Parse for RsxRender {
                 None
             };
 
-        let root = { input.parse::<AmbiguousElement>() }?;
-        if !input.is_empty() {
-            return Err(Error::new(
-                input.span(),
-                "Currently only one element is allowed per component. Try wrapping your list of components in a `Fragment` tag",
-            ));
+        let mut roots = Vec::new();
+        while !input.is_empty() {
+            roots.push(input.parse::<AmbiguousElement>()?);
         }
 
         Ok(Self {
-            root,
+            roots,
             custom_context,
         })
     }
@@ -78,27 +75,41 @@ impl Parse for RsxRender {
 
 impl ToTokens for RsxRender {
     fn to_tokens(&self, out_tokens: &mut TokenStream2) {
-        let inner = &self.root;
-        let output = match &self.custom_context {
-            // The `in ctx` pattern allows directly rendering
-            Some(ident) => {
-                quote! {
-                    #ident.render(dioxus::prelude::LazyNodes::new(move |__ctx|{
-                        let bump = &__ctx.bump();
-                        #inner
-                    }))
-                }
+        let inner = if self.roots.len() == 1 {
+            let inner = &self.roots[0];
+            quote! {#inner}
+        } else {
+            let childs = &self.roots;
+            let children = quote! {
+                ChildrenList::new(__ctx)
+                    #( .add_child(#childs) )*
+                    .finish()
+            };
+            quote! {
+                // #key_token,
+                dioxus::builder::vfragment(
+                    __ctx,
+                    None,
+                    #children
+                )
             }
+        };
+
+        match &self.custom_context {
+            // The `in ctx` pattern allows directly rendering
+            Some(ident) => out_tokens.append_all(quote! {
+                #ident.render(dioxus::prelude::LazyNodes::new(move |__ctx|{
+                    let bump = &__ctx.bump();
+                    #inner
+                }))
+            }),
             // Otherwise we just build the LazyNode wrapper
-            None => {
-                quote! {
-                    dioxus::prelude::LazyNodes::new(move |__ctx|{
-                        let bump = &__ctx.bump();
-                        #inner
-                     })
-                }
-            }
+            None => out_tokens.append_all(quote! {
+                dioxus::prelude::LazyNodes::new(move |__ctx|{
+                    let bump = &__ctx.bump();
+                    #inner
+                 })
+            }),
         };
-        output.to_tokens(out_tokens)
     }
 }

+ 1 - 1
packages/core/.vscode/settings.json

@@ -1,3 +1,3 @@
 {
-    "rust-analyzer.inlayHints.enable": false
+    "rust-analyzer.inlayHints.enable": true
 }

+ 1 - 0
packages/core/examples/borrowed.rs

@@ -39,6 +39,7 @@ fn app(ctx: Context<Props>) -> VNode {
                     .item_handler(Callback(set_val.clone()))
                     .build(),
                 None,
+                &[],
             ));
         }
         root.finish()

+ 2 - 0
packages/core/examples/nested.rs

@@ -15,9 +15,11 @@ static Header: FC<()> = |ctx| {
     ctx.render(dioxus::prelude::LazyNodes::new(|nodectx| {
         builder::ElementBuilder::new(nodectx, "div")
             .child(VNode::Component(nodectx.bump().alloc(VComponent::new(
+                nodectx,
                 Bottom,
                 (),
                 None,
+                &[],
             ))))
             .finish()
     }))

+ 27 - 2
packages/core/src/arena.rs

@@ -9,9 +9,9 @@ use generational_arena::Arena;
 use crate::innerlude::*;
 
 #[derive(Clone)]
-pub struct ScopeArena(Rc<RefCell<ScopeArenaInner>>);
+pub struct ScopeArena(pub Rc<RefCell<ScopeArenaInner>>);
 
-struct ScopeArenaInner {
+pub struct ScopeArenaInner {
     pub(crate) arena: UnsafeCell<Arena<Scope>>,
     locks: HashMap<ScopeIdx, MutStatus>,
 }
@@ -61,6 +61,31 @@ impl ScopeArena {
         // todo!()
     }
 
+    pub fn with_scope<'b, O: 'static>(
+        &'b self,
+        id: ScopeIdx,
+        f: impl FnOnce(&'b mut Scope) -> O,
+    ) -> Result<O> {
+        todo!()
+    }
+
+    // return a bumpframe with a lifetime attached to the arena borrow
+    // this is useful for merging lifetimes
+    pub fn with_scope_vnode<'b>(
+        &self,
+        id: ScopeIdx,
+        f: impl FnOnce(&mut Scope) -> &VNode<'b>,
+    ) -> Result<&VNode<'b>> {
+        todo!()
+    }
+
+    pub fn try_remove(&mut self, id: ScopeIdx) -> Result<Scope> {
+        let inner = unsafe { &mut *self.0.borrow().arena.get() };
+        inner
+            .remove(id)
+            .ok_or_else(|| Error::FatalInternal("Scope not found"))
+    }
+
     unsafe fn inner_unchecked<'s>() -> &'s mut Arena<Scope> {
         todo!()
     }

+ 12 - 117
packages/core/src/component.rs

@@ -7,21 +7,14 @@
 
 use crate::innerlude::FC;
 
-pub type ScopeIdx = generational_arena::Index;
-
-pub trait Properties: PartialEq {
+pub unsafe trait Properties: PartialEq + Sized {
     type Builder;
+    const CAN_BE_MEMOIZED: bool;
     fn builder() -> Self::Builder;
 }
 
-pub struct EmptyBuilder;
-impl EmptyBuilder {
-    pub fn build(self) -> () {
-        ()
-    }
-}
-
-impl Properties for () {
+unsafe impl Properties for () {
+    const CAN_BE_MEMOIZED: bool = true;
     type Builder = EmptyBuilder;
 
     fn builder() -> Self::Builder {
@@ -29,112 +22,14 @@ impl Properties for () {
     }
 }
 
-pub fn fc_to_builder<T: Properties>(_f: FC<T>) -> T::Builder {
-    T::builder()
-}
-
-mod testing {
-    use std::any::Any;
-
-    // trait PossibleProps {
-    //     type POut: PartialEq;
-    //     fn as_partial_eq(&self) -> Option<&Self::POut> {
-    //         None
-    //     }
-    // }
-
-    // impl<T: PartialEq> PossibleProps for T {
-    //     type POut = Self;
-    // }
-
-    // struct SomeProps2<'a> {
-    //     inner: &'a str,
-    // }
-
-    // Fallback trait for to all types to default to `false`.
-    trait NotEq {
-        const IS_EQ: bool = false;
-    }
-    impl<T> NotEq for T {}
-
-    // Concrete wrapper type where `IS_COPY` becomes `true` if `T: Copy`.
-    struct IsEq<G, T>(std::marker::PhantomData<(G, T)>);
-
-    impl<G: PartialEq, T: PartialEq<G>> IsEq<G, T> {
-        // Because this is implemented directly on `IsCopy`, it has priority over
-        // the `NotCopy` trait impl.
-        //
-        // Note: this is a *totally different* associated constant from that in
-        // `NotCopy`. This does not specialize the `NotCopy` trait impl on `IsCopy`.
-        const IS_EQ: bool = true;
-    }
-
-    #[derive(PartialEq)]
-    struct SomeProps {
-        inner: &'static str,
-    }
-
-    struct SomeProps2 {
-        inner: &'static str,
-    }
-
-    #[test]
-    fn test() {
-        let g = IsEq::<SomeProps, SomeProps>::IS_EQ;
-
-        // let g = IsEq::<Vec<u32>>::IS_COPY;
-        // let g = IsEq::<u32>::IS_COPY;
-        // dbg!(g);
-
-        // let props = SomeProps { inner: "asd" };
-
-        // let intermediate: Box<dyn PartialEq<SomeProps>> = Box::new(props);
-        // let as_any: Box<dyn Any> = Box::new(intermediate);
-
-        // let as_partialeq = as_any
-        //     .downcast_ref::<Box<dyn PartialEq<SomeProps>>>()
-        //     .unwrap();
-    }
-
-    // struct blah {}
-    // #[reorder_args]
-    pub fn blah(a: i32, b: &str, c: &str) {}
-
-    // pub mod blah {
-    //     pub const a: u8 = 0;
-    //     pub const b: u8 = 1;
-    // }
-
-    trait Eat {}
-    impl Eat for fn() {}
-    impl<T> Eat for fn(T) {}
-    impl<T, K> Eat for fn(T, K) {}
-
-    mod other {
-        use super::blah;
-        fn test2() {
-            // rsx!{
-            //     div {
-            //         Ele {
-            //             a: 10,
-            //             b: "asd"
-            //             c: impl Fn() -> ()
-            //         }
-            //     }
-            // }
-
-            // becomes
-
-            // const reorder: fn(_, _) = |a, b| {};
-            // blah::META;
-            // let a = 10;
-            // let b = "asd";
-            // let g = [10, 10.0];
-            // let c = g.a;
-
-            // blah(10, "asd");
-        }
+pub struct EmptyBuilder;
+impl EmptyBuilder {
+    #[inline]
+    pub fn build(self) -> () {
+        ()
     }
 }
 
-mod style {}
+pub fn fc_to_builder<T: Properties>(_: FC<T>) -> T::Builder {
+    T::builder()
+}

+ 198 - 112
packages/core/src/diff.rs

@@ -32,7 +32,7 @@
 //!
 //! More info on how to improve this diffing algorithm:
 //!  - https://hacks.mozilla.org/2019/03/fast-bump-allocated-virtual-doms-with-rust-and-wasm/
-use crate::innerlude::*;
+use crate::{arena::ScopeArena, innerlude::*};
 use bumpalo::Bump;
 use fxhash::{FxHashMap, FxHashSet};
 use generational_arena::Arena;
@@ -59,50 +59,29 @@ use std::{
 /// subscriptions and props changes.
 pub struct DiffMachine<'a> {
     pub create_diffs: bool,
+    pub cur_idx: ScopeIdx,
     pub change_list: EditMachine<'a>,
     pub diffed: FxHashSet<ScopeIdx>,
-    pub lifecycle_events: VecDeque<LifeCycleEvent<'a>>,
-}
-pub enum LifeCycleEvent<'a> {
-    Mount {
-        caller: Weak<dyn Fn(&Scope) -> VNode + 'a>,
-        stable_scope_addr: Weak<VCompAssociatedScope>,
-        root_id: u32,
-    },
-    PropsChanged {
-        caller: Weak<dyn Fn(&Scope) -> VNode + 'a>,
-        stable_scope_addr: Weak<VCompAssociatedScope>,
-        root_id: u32,
-    },
-    SameProps {
-        caller: Weak<dyn Fn(&Scope) -> VNode + 'a>,
-        stable_scope_addr: Weak<VCompAssociatedScope>,
-        root_id: u32,
-    },
-    Replace {
-        caller: Weak<dyn Fn(&Scope) -> VNode + 'a>,
-        old_scope: Weak<VCompAssociatedScope>,
-        new_scope: Weak<VCompAssociatedScope>,
-        root_id: u32,
-    },
-    Remove {
-        stable_scope_addr: Weak<VCompAssociatedScope>,
-        root_id: u32,
-    },
+    pub components: ScopeArena,
+    pub event_queue: EventQueue,
+    pub seen_nodes: FxHashSet<ScopeIdx>,
 }
 
 static COUNTER: AtomicU32 = AtomicU32::new(1);
-fn get_id() -> u32 {
+fn next_id() -> u32 {
     COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed)
 }
 
 impl<'a> DiffMachine<'a> {
-    pub fn new() -> Self {
+    pub fn new(components: ScopeArena, cur_idx: ScopeIdx, event_queue: EventQueue) -> Self {
         Self {
+            components,
+            cur_idx,
+            event_queue,
             create_diffs: true,
-            lifecycle_events: VecDeque::new(),
             change_list: EditMachine::new(),
             diffed: FxHashSet::default(),
+            seen_nodes: FxHashSet::default(),
         }
     }
 
@@ -110,15 +89,15 @@ impl<'a> DiffMachine<'a> {
         self.change_list.emitter
     }
 
-    pub fn diff_node(&mut self, old: &VNode<'a>, new: &VNode<'a>) {
+    pub fn diff_node(&mut self, old_node: &VNode<'a>, new_node: &VNode<'a>) {
         // pub fn diff_node(&mut self, old: &VNode<'a>, new: &VNode<'a>) {
         /*
         For each valid case, we "commit traversal", meaning we save this current position in the tree.
         Then, we diff and queue an edit event (via chagelist). s single trees - when components show up, we save that traversal and then re-enter later.
         When re-entering, we reuse the EditList in DiffState
         */
-        match (old, new) {
-            (VNode::Text(VText { text: old_text }), VNode::Text(VText { text: new_text })) => {
+        match (old_node, new_node) {
+            (VNode::Text(old_text), VNode::Text(new_text)) => {
                 if old_text != new_text {
                     self.change_list.commit_traversal();
                     self.change_list.set_text(new_text);
@@ -127,13 +106,13 @@ impl<'a> DiffMachine<'a> {
 
             (VNode::Text(_), VNode::Element(_)) => {
                 self.change_list.commit_traversal();
-                self.create(new);
+                self.create(new_node);
                 self.change_list.replace_with();
             }
 
             (VNode::Element(_), VNode::Text(_)) => {
                 self.change_list.commit_traversal();
-                self.create(new);
+                self.create(new_node);
                 self.change_list.replace_with();
             }
 
@@ -151,55 +130,86 @@ impl<'a> DiffMachine<'a> {
             }
 
             (VNode::Component(cold), VNode::Component(cnew)) => {
-                // todo!("should not happen")
-                // self.change_list.commit_traversal();
+                // Make sure we're dealing with the same component (by function pointer)
                 if cold.user_fc == cnew.user_fc {
-                    // todo: create a stable addr
-                    let caller = Rc::downgrade(&cnew.caller);
-                    let id = cold.stable_addr.borrow().unwrap();
-                    *cnew.stable_addr.borrow_mut() = Some(id);
-                    *cnew.ass_scope.borrow_mut() = *cold.ass_scope.borrow();
-
-                    let scope = Rc::downgrade(&cold.ass_scope);
-                    self.lifecycle_events
-                        .push_back(LifeCycleEvent::PropsChanged {
-                            caller,
-                            root_id: id,
-                            stable_scope_addr: scope,
-                        });
+                    // Make sure the new component vnode is referencing the right scope id
+                    let scope_id = cold.ass_scope.borrow().clone();
+                    *cnew.ass_scope.borrow_mut() = scope_id;
+
+                    // make sure the component's caller function is up to date
+                    self.components
+                        .with_scope(scope_id.unwrap(), |scope| {
+                            scope.caller = Rc::downgrade(&cnew.caller)
+                        })
+                        .unwrap();
+
+                    // React doesn't automatically memoize, but we do.
+                    // The cost is low enough to make it worth checking
+                    let should_render = match cold.comparator {
+                        Some(comparator) => comparator(cnew),
+                        None => true,
+                    };
+
+                    if should_render {
+                        self.change_list.commit_traversal();
+                        self.components
+                            .with_scope(scope_id.unwrap(), |f| {
+                                f.run_scope().unwrap();
+                            })
+                            .unwrap();
+                        // diff_machine.change_list.load_known_root(root_id);
+                        // run the scope
+                        //
+                    } else {
+                        // Component has memoized itself and doesn't need to be re-rendered.
+                        // We still need to make sure the child's props are up-to-date.
+                        // Don't commit traversal
+                    }
                 } else {
-                    let caller = Rc::downgrade(&cnew.caller);
-                    let id = cold.stable_addr.borrow().unwrap();
-                    let old_scope = Rc::downgrade(&cold.ass_scope);
-                    let new_scope = Rc::downgrade(&cnew.ass_scope);
-
-                    self.lifecycle_events.push_back(LifeCycleEvent::Replace {
-                        caller,
-                        root_id: id,
-                        old_scope,
-                        new_scope,
-                    });
+                    // A new component has shown up! We need to destroy the old node
+
+                    // Wipe the old one and plant the new one
+                    self.change_list.commit_traversal();
+                    self.create(new_node);
+                    self.change_list.replace_with();
+
+                    // Now we need to remove the old scope and all of its descendents
+                    let old_scope = cold.ass_scope.borrow().as_ref().unwrap().clone();
+                    self.destroy_scopes(old_scope);
                 }
             }
 
             // todo: knock out any listeners
-            (_, VNode::Component(_new)) => {
+            (_, VNode::Component(_)) => {
                 self.change_list.commit_traversal();
+                self.create(new_node);
+                self.change_list.replace_with();
             }
 
+            // A component is being torn down in favor of a non-component node
             (VNode::Component(_old), _) => {
-                todo!("Usage of component VNode not currently supported");
+                self.change_list.commit_traversal();
+                self.create(new_node);
+                self.change_list.replace_with();
+
+                // Destroy the original scope and any of its children
+                self.destroy_scopes(_old.ass_scope.borrow().unwrap());
             }
 
+            // Anything suspended is not enabled ATM
             (VNode::Suspended, _) | (_, VNode::Suspended) => {
                 todo!("Suspended components not currently available")
             }
 
-            (VNode::Fragment(_), VNode::Fragment(_)) => {
+            // Fragments are special
+            // we actually have to remove a bunch of nodes
+            (VNode::Fragment(_), _) => {
+                todo!("Fragments not currently supported in diffing")
+            }
+
+            (_, VNode::Fragment(_)) => {
                 todo!("Fragments not currently supported in diffing")
             }
-            (_, VNode::Fragment(_)) => todo!("Fragments not currently supported in diffing"),
-            (VNode::Fragment(_), _) => todo!("Fragments not currently supported in diffing"),
         }
     }
 
@@ -215,11 +225,11 @@ impl<'a> DiffMachine<'a> {
     fn create(&mut self, node: &VNode<'a>) {
         debug_assert!(self.change_list.traversal_is_committed());
         match node {
-            VNode::Text(VText { text }) => {
+            VNode::Text(text) => {
                 self.change_list.create_text_node(text);
             }
             VNode::Element(&VElement {
-                key: _,
+                key,
                 tag_name,
                 listeners,
                 attributes,
@@ -250,7 +260,7 @@ impl<'a> DiffMachine<'a> {
                 // text content, and finally (3) append the text node to this
                 // parent.
                 if children.len() == 1 {
-                    if let VNode::Text(VText { text }) = children[0] {
+                    if let VNode::Text(text) = children[0] {
                         self.change_list.set_text(text);
                         return;
                     }
@@ -258,35 +268,121 @@ impl<'a> DiffMachine<'a> {
 
                 for child in children {
                     self.create(child);
-                    self.change_list.append_child();
+                    if let VNode::Fragment(_) = child {
+                        // do nothing
+                        // fragments append themselves
+                    } else {
+                        self.change_list.append_child();
+                    }
                 }
             }
 
-            /*
-            todo: integrate re-entrace
-            */
             VNode::Component(component) => {
                 self.change_list
                     .create_text_node("placeholder for vcomponent");
 
-                let id = get_id();
-                *component.stable_addr.as_ref().borrow_mut() = Some(id);
-                self.change_list.save_known_root(id);
-                let scope = Rc::downgrade(&component.ass_scope);
-                self.lifecycle_events.push_back(LifeCycleEvent::Mount {
-                    caller: Rc::downgrade(&component.caller),
-                    root_id: id,
-                    stable_scope_addr: scope,
-                });
+                let root_id = next_id();
+                self.change_list.save_known_root(root_id);
+
+                log::debug!("Mounting a new component");
+                let caller: Weak<OpaqueComponent> = Rc::downgrade(&component.caller);
+
+                // We're modifying the component arena while holding onto references into the assoiated bump arenas of its children
+                // those references are stable, even if the component arena moves around in memory, thanks to the bump arenas.
+                // However, there is no way to convey this to rust, so we need to use unsafe to pierce through the lifetime.
+
+                let parent_idx = self.cur_idx;
+
+                // Insert a new scope into our component list
+                let idx = self
+                    .components
+                    .with(|components| {
+                        components.insert_with(|new_idx| {
+                            let parent_scope = self.components.try_get(parent_idx).unwrap();
+                            let height = parent_scope.height + 1;
+                            Scope::new(
+                                caller,
+                                new_idx,
+                                Some(parent_idx),
+                                height,
+                                self.event_queue.new_channel(height, new_idx),
+                                self.components.clone(),
+                                component.children,
+                            )
+                        })
+                    })
+                    .unwrap();
+
+                {
+                    let cur_component = self.components.try_get_mut(idx).unwrap();
+                    let mut ch = cur_component.descendents.borrow_mut();
+                    ch.insert(idx);
+                    std::mem::drop(ch);
+                }
+
+                // yaaaaay lifetimes out of thin air
+                // really tho, we're merging the frame lifetimes together
+                let inner: &'a mut _ = unsafe { &mut *self.components.0.borrow().arena.get() };
+                let new_component = inner.get_mut(idx).unwrap();
+
+                // Actually initialize the caller's slot with the right address
+                *component.ass_scope.borrow_mut() = Some(idx);
+
+                // Run the scope for one iteration to initialize it
+                new_component.run_scope().unwrap();
+
+                // And then run the diff algorithm
+                self.diff_node(new_component.old_frame(), new_component.next_frame());
+
+                // Finally, insert this node as a seen node.
+                self.seen_nodes.insert(idx);
+            }
+
+            // we go the the "known root" but only operate on a sibling basis
+            VNode::Fragment(frag) => {
+                // create the children directly in the space
+                for child in frag.children {
+                    self.create(child);
+                    self.change_list.append_child();
+                }
             }
+
             VNode::Suspended => {
                 todo!("Creation of VNode::Suspended not yet supported")
             }
-            VNode::Fragment(frag) => {
-                //
-                todo!("Cannot current create fragments")
+        }
+    }
+
+    /// Destroy a scope and all of its descendents.
+    ///
+    /// Calling this will run the destuctors on all hooks in the tree.
+    /// It will also add the destroyed nodes to the `seen_nodes` cache to prevent them from being renderered.
+    fn destroy_scopes(&mut self, old_scope: ScopeIdx) {
+        let mut nodes_to_delete = vec![old_scope];
+        let mut scopes_to_explore = vec![old_scope];
+
+        // explore the scope tree breadth first
+        while let Some(scope_id) = scopes_to_explore.pop() {
+            // If we're planning on deleting this node, then we don't need to both rendering it
+            self.seen_nodes.insert(scope_id);
+            let scope = self.components.try_get(scope_id).unwrap();
+            for child in scope.descendents.borrow().iter() {
+                // Add this node to be explored
+                scopes_to_explore.push(child.clone());
+
+                // Also add it for deletion
+                nodes_to_delete.push(child.clone());
             }
         }
+
+        // Delete all scopes that we found as part of this subtree
+        for node in nodes_to_delete {
+            log::debug!("Removing scope {:#?}", node);
+            let _scope = self.components.try_remove(node).unwrap();
+            // do anything we need to do to delete the scope
+            // I think we need to run the destructors on the hooks
+            // TODO
+        }
     }
 
     // Diff event listeners between `old` and `new`.
@@ -297,7 +393,6 @@ impl<'a> DiffMachine<'a> {
     //
     // The change list stack is left unchanged.
     fn diff_listeners(&mut self, old: &[Listener<'_>], new: &[Listener<'_>]) {
-        // fn diff_listeners(&mut self, old: &[Listener<'a>], new: &[Listener<'a>]) {
         if !old.is_empty() || !new.is_empty() {
             self.change_list.commit_traversal();
         }
@@ -319,26 +414,15 @@ impl<'a> DiffMachine<'a> {
                             .update_event_listener(event_type, new_l.scope, new_l.id)
                     }
 
-                    // if let Some(scope) = self.current_idx {
-                    //     let cb = CbIdx::from_gi_index(scope, l_idx);
-                    // self.change_list
-                    //     .update_event_listener(event_type, new_l.scope, new_l.id);
-                    // }
-
                     continue 'outer1;
                 }
             }
 
-            // if let Some(scope) = self.current_idx {
-            // let cb = CbIdx::from_gi_index(scope, l_idx);
             self.change_list
                 .new_event_listener(event_type, new_l.scope, new_l.id);
-            // }
         }
 
         'outer2: for old_l in old {
-            // registry.remove(old_l);
-
             for new_l in new {
                 if new_l.event == old_l.event {
                     continue 'outer2;
@@ -363,6 +447,9 @@ impl<'a> DiffMachine<'a> {
     ) {
         // Do O(n^2) passes to add/update and remove attributes, since
         // there are almost always very few attributes.
+        //
+        // The "fast" path is when the list of attributes name is identical and in the same order
+        // With the Rsx and Html macros, this will almost always be the case
         'outer: for new_attr in new {
             if new_attr.is_volatile() {
                 self.change_list.commit_traversal();
@@ -380,6 +467,8 @@ impl<'a> DiffMachine<'a> {
                             );
                         }
                         continue 'outer;
+                    } else {
+                        // names are different, a varying order of attributes has arrived
                     }
                 }
 
@@ -420,22 +509,17 @@ impl<'a> DiffMachine<'a> {
 
         if new.len() == 1 {
             match (old.first(), &new[0]) {
-                (
-                    Some(&VNode::Text(VText { text: old_text })),
-                    &VNode::Text(VText { text: new_text }),
-                ) if old_text == new_text => {
+                (Some(&VNode::Text(old_text)), &VNode::Text(new_text)) if old_text == new_text => {
                     // Don't take this fast path...
                 }
 
-                (_, &VNode::Text(VText { text })) => {
+                (_, &VNode::Text(text)) => {
                     self.change_list.commit_traversal();
                     self.change_list.set_text(text);
-                    // for o in old {
-                    //     registry.remove_subtree(o);
-                    // }
                     return;
                 }
 
+                // todo: any more optimizations
                 (_, _) => {}
             }
         }
@@ -462,6 +546,7 @@ impl<'a> DiffMachine<'a> {
 
         if new_is_keyed && old_is_keyed {
             let t = self.change_list.next_temporary();
+            self.diff_keyed_children(old, new);
             self.change_list.set_next_temporary(t);
         } else {
             self.diff_non_keyed_children(old, new);
@@ -977,11 +1062,12 @@ impl<'a> DiffMachine<'a> {
                 // self.change_list
                 //     .create_text_node("placeholder for vcomponent");
 
-                let root_id = vcomp.stable_addr.as_ref().borrow().unwrap();
-                self.lifecycle_events.push_back(LifeCycleEvent::Remove {
-                    root_id,
-                    stable_scope_addr: Rc::downgrade(&vcomp.ass_scope),
-                })
+                todo!()
+                // let root_id = vcomp.stable_addr.as_ref().borrow().unwrap();
+                // self.lifecycle_events.push_back(LifeCycleEvent::Remove {
+                //     root_id,
+                //     stable_scope_addr: Rc::downgrade(&vcomp.ass_scope),
+                // })
                 // let id = get_id();
                 // *component.stable_addr.as_ref().borrow_mut() = Some(id);
                 // self.change_list.save_known_root(id);

+ 2 - 14
packages/core/src/lib.rs

@@ -120,14 +120,12 @@ pub mod prelude {
 
     pub use crate::nodebuilder::LazyNodes;
 
+    pub use crate::nodebuilder::ChildrenList;
     pub use crate::virtual_dom::NodeCtx;
     // pub use nodes::iterables::IterableNodes;
     /// This type alias is an internal way of abstracting over the static functions that represent components.
     pub use crate::innerlude::FC;
 
-    // TODO @Jon, fix this
-    // hack the VNode type until VirtualNode is fixed in the macro crate
-
     // expose our bumpalo type
     pub use bumpalo;
     pub use bumpalo::Bump;
@@ -139,19 +137,9 @@ pub mod prelude {
 
     pub use dioxus_core_macro::{format_args_f, html, rsx, Props};
 
-    pub use crate::component::ScopeIdx;
     pub use crate::diff::DiffMachine;
+    pub use crate::virtual_dom::ScopeIdx;
 
     pub use crate::debug_renderer::DebugRenderer;
-    pub use crate::dioxus_main;
     pub use crate::hooks::*;
 }
-
-#[macro_export]
-macro_rules! dioxus_main {
-    ($i:ident) => {
-        fn main() {
-            todo!("this macro is a placeholder for launching a dioxus app on different platforms. \nYou probably don't want to use this, but it's okay for small apps.")
-        }
-    };
-}

+ 59 - 8
packages/core/src/nodebuilder.rs

@@ -1,12 +1,12 @@
 //! Helpers for building virtual DOM VNodes.
 
-use std::{any::Any, borrow::BorrowMut, intrinsics::transmute, u128};
+use std::{any::Any, borrow::BorrowMut, fmt::Arguments, intrinsics::transmute, u128};
 
 use crate::{
     events::VirtualEvent,
     innerlude::{Properties, VComponent, FC},
     nodes::{Attribute, Listener, NodeKey, VNode},
-    prelude::VElement,
+    prelude::{VElement, VFragment},
     virtual_dom::NodeCtx,
 };
 
@@ -269,6 +269,20 @@ where
         self
     }
 
+    pub fn key2(mut self, args: Arguments) -> Self {
+        let key = match args.as_str() {
+            Some(static_str) => static_str,
+            None => {
+                use bumpalo::core_alloc::fmt::Write;
+                let mut s = bumpalo::collections::String::new_in(self.ctx.bump());
+                s.write_fmt(args).unwrap();
+                s.into_bump_str()
+            }
+        };
+        self.key = NodeKey(Some(key));
+        self
+    }
+
     /// Create the virtual DOM VNode described by this builder.
     ///
     /// # Example
@@ -650,17 +664,54 @@ pub fn attr<'a>(name: &'static str, value: &'a str) -> Attribute<'a> {
     Attribute { name, value }
 }
 
-pub fn virtual_child<'a, T: Properties>(
+pub fn virtual_child<'a, T: Properties + 'a>(
     ctx: &NodeCtx<'a>,
     f: FC<T>,
     props: T,
     key: Option<&'a str>, // key: NodeKey<'a>,
+    children: &'a [VNode<'a>],
 ) -> VNode<'a> {
     // currently concerned about if props have a custom drop implementation
     // might override it with the props macro
-    todo!()
-    // VNode::Component(
-    //     ctx.bump()
-    //         .alloc(crate::nodes::VComponent::new(f, props, key)),
-    // )
+    // todo!()
+    VNode::Component(
+        ctx.bump()
+            .alloc(crate::nodes::VComponent::new(ctx, f, props, key, children)),
+        // ctx.bump()
+        //     .alloc(crate::nodes::VComponent::new(f, props, key)),
+    )
+}
+
+pub fn vfragment<'a>(
+    ctx: &NodeCtx<'a>,
+    key: Option<&'a str>, // key: NodeKey<'a>,
+    children: &'a [VNode<'a>],
+) -> VNode<'a> {
+    VNode::Fragment(ctx.bump().alloc(VFragment::new(key, children)))
+}
+
+pub struct ChildrenList<'a, 'b> {
+    ctx: &'b NodeCtx<'a>,
+    children: bumpalo::collections::Vec<'a, VNode<'a>>,
+}
+
+impl<'a, 'b> ChildrenList<'a, 'b> {
+    pub fn new(ctx: &'b NodeCtx<'a>) -> Self {
+        Self {
+            ctx,
+            children: bumpalo::collections::Vec::new_in(ctx.bump()),
+        }
+    }
+
+    pub fn add_child(mut self, nodes: impl IntoIterator<Item = impl IntoVNode<'a>>) -> Self {
+        for item in nodes {
+            let child = item.into_vnode(&self.ctx);
+            self.children.push(child);
+        }
+        self
+    }
+
+    pub fn finish(self) -> &'a [VNode<'a>] {
+        self.children.into_bump_slice()
+    }
 }

+ 107 - 69
packages/core/src/nodes.rs

@@ -7,6 +7,8 @@ use crate::{
     events::VirtualEvent,
     innerlude::{Context, Properties, Scope, ScopeIdx, FC},
     nodebuilder::text3,
+    virtual_dom::NodeCtx,
+    // support::NodeCtx,
 };
 use bumpalo::Bump;
 use std::{
@@ -27,7 +29,7 @@ pub enum VNode<'src> {
     Element(&'src VElement<'src>),
 
     /// A text node (node type `TEXT_NODE`).
-    Text(VText<'src>),
+    Text(&'src str),
 
     /// A fragment is a "virtual position" in the DOM
     /// Fragments may have children and keys
@@ -46,11 +48,11 @@ pub enum VNode<'src> {
 impl<'a> Clone for VNode<'a> {
     fn clone(&self) -> Self {
         match self {
-            VNode::Element(el) => VNode::Element(el),
-            VNode::Text(origi) => VNode::Text(VText { text: origi.text }),
-            VNode::Fragment(frag) => VNode::Fragment(frag),
+            VNode::Element(element) => VNode::Element(element),
+            VNode::Text(text) => VNode::Text(text),
+            VNode::Fragment(fragment) => VNode::Fragment(fragment),
+            VNode::Component(component) => VNode::Component(component),
             VNode::Suspended => VNode::Suspended,
-            VNode::Component(c) => VNode::Component(c),
         }
     }
 }
@@ -86,7 +88,7 @@ impl<'a> VNode<'a> {
     /// Construct a new text node with the given text.
     #[inline]
     pub fn text(text: &'a str) -> VNode<'a> {
-        VNode::Text(VText { text })
+        VNode::Text(text)
     }
 
     pub fn text_args(bump: &'a Bump, args: Arguments) -> VNode<'a> {
@@ -210,51 +212,34 @@ impl<'a> NodeKey<'a> {
     }
 }
 
-#[derive(Debug, PartialEq)]
-pub struct VText<'bump> {
-    pub text: &'bump str,
-}
-
-impl<'b> Clone for VText<'b> {
-    fn clone(&self) -> Self {
-        Self { text: self.text }
-    }
-}
-
-impl<'a> VText<'a> {
-    // / Create an new `VText` instance with the specified text.
-    pub fn new(text: &'a str) -> Self {
-        VText { text: text.into() }
-    }
-}
-
 // ==============================
 //   Custom components
 // ==============================
 
 /// Virtual Components for custom user-defined components
 /// Only supports the functional syntax
-pub type StableScopeAddres = RefCell<Option<u32>>;
-pub type VCompAssociatedScope = RefCell<Option<ScopeIdx>>;
+pub type StableScopeAddres = Option<u32>;
+pub type VCompAssociatedScope = Option<ScopeIdx>;
 
 pub struct VComponent<'src> {
     pub key: NodeKey<'src>,
 
-    pub stable_addr: Rc<StableScopeAddres>,
-    pub ass_scope: Rc<VCompAssociatedScope>,
+    pub stable_addr: RefCell<StableScopeAddres>,
+    pub ass_scope: RefCell<VCompAssociatedScope>,
 
     // pub comparator: Rc<dyn Fn(&VComponent) -> bool + 'src>,
-    pub caller: Rc<dyn Fn(&Scope) -> VNode + 'src>,
+    pub caller: Rc<dyn Fn(&Scope) -> VNode>,
 
     pub children: &'src [VNode<'src>],
 
+    pub comparator: Option<&'src dyn Fn(&VComponent) -> bool>,
+
     // a pointer into the bump arena (given by the 'src lifetime)
     // raw_props: Box<dyn Any>,
-    // raw_props: *const (),
+    raw_props: *const (),
 
     // a pointer to the raw fn typ
     pub user_fc: *const (),
-    _p: PhantomData<&'src ()>,
 }
 
 impl<'a> VComponent<'a> {
@@ -264,70 +249,123 @@ impl<'a> VComponent<'a> {
     // TODO: lift the requirement that props need to be static
     // we want them to borrow references... maybe force implementing a "to_static_unsafe" trait
 
-    pub fn new<P: Properties>(
+    pub fn new<P: Properties + 'a>(
+        // bump: &'a Bump,
+        ctx: &NodeCtx<'a>,
         component: FC<P>,
         // props: bumpalo::boxed::Box<'a, P>,
         props: P,
         key: Option<&'a str>,
+        children: &'a [VNode<'a>],
     ) -> Self {
         // pub fn new<P: Properties + 'a>(component: FC<P>, props: P, key: Option<&'a str>) -> Self {
         // let bad_props = unsafe { transmogrify(props) };
+        let bump = ctx.bump();
         let caller_ref = component as *const ();
-
-        // let raw_props = props as *const P as *const ();
-
-        // let props_comparator = move |other: &VComponent| {
-        //     // Safety:
-        //     // We are guaranteed that the props will be of the same type because
-        //     // there is no way to create a VComponent other than this `new` method.
-        //     //
-        //     // Therefore, if the render functions are identical (by address), then so will be
-        //     // props type paramter (because it is the same render function). Therefore, we can be
-        //     // sure
-        //     if caller_ref == other.user_fc {
-        //         let g = other.raw_ctx.downcast_ref::<P>().unwrap();
-        //         // let real_other = unsafe { &*(other.raw_props as *const _ as *const P) };
-        //         &props == g
-        //     } else {
-        //         false
-        //     }
-        // };
+        let props = bump.alloc(props);
+
+        let raw_props = props as *const P as *const ();
+
+        let comparator: Option<&dyn Fn(&VComponent) -> bool> = {
+            if P::CAN_BE_MEMOIZED {
+                Some(bump.alloc(move |other: &VComponent| {
+                    // Safety:
+                    // We are guaranteed that the props will be of the same type because
+                    // there is no way to create a VComponent other than this `new` method.
+                    //
+                    // Therefore, if the render functions are identical (by address), then so will be
+                    // props type paramter (because it is the same render function). Therefore, we can be
+                    // sure
+                    if caller_ref == other.user_fc {
+                        // let g = other.raw_ctx.downcast_ref::<P>().unwrap();
+                        let real_other = unsafe { &*(other.raw_props as *const _ as *const P) };
+                        &props == &real_other
+                    } else {
+                        false
+                    }
+                }))
+            } else {
+                None
+            }
+        };
 
         // let prref: &'a P = props.as_ref();
 
-        let caller: Rc<dyn Fn(&Scope) -> VNode> = Rc::new(move |scope| {
-            //
-            // let props2 = bad_props;
-            // props.as_ref()
-            // let ctx = Context {
-            //     props: prref,
-            //     scope,
-            // };
-            todo!()
-            // component(ctx)
-        });
-        // let caller = Rc::new(create_closure(component, raw_props));
+        // let r = create_closure(component, raw_props);
+        // let caller: Rc<dyn for<'g> Fn(&'g Scope) -> VNode<'g>> = Rc::new(move |scope| {
+        //     // r(scope);
+        //     //
+        //     // let props2 = bad_props;
+        //     // props.as_ref();
+        //     // let ctx = Context {
+        //     //     props: prref,
+        //     //     scope,
+        //     // };
+        //     // let ctx: Context<'g, P> = todo!();
+        //     // todo!()
+        //     // let r = component(ctx);
+        //     todo!()
+        // });
+        let caller = create_closure(component, raw_props);
+
+        // let caller: Rc<dyn Fn(&Scope) -> VNode> = Rc::new(create_closure(component, raw_props));
 
         let key = match key {
             Some(key) => NodeKey::new(key),
             None => NodeKey(None),
         };
 
+        // raw_props: Box::new(props),
+        // comparator: Rc::new(props_comparator),
         Self {
             key,
-            ass_scope: Rc::new(RefCell::new(None)),
+            ass_scope: RefCell::new(None),
             user_fc: caller_ref,
-            // raw_props: Box::new(props),
-            _p: PhantomData,
-            children: &[],
+            comparator,
+            raw_props,
+            children,
             caller,
-            // comparator: Rc::new(props_comparator),
-            stable_addr: Rc::new(RefCell::new(None)),
+            stable_addr: RefCell::new(None),
         }
     }
 }
 
+type Captured<'a> = Rc<dyn for<'r> Fn(&'r Scope) -> VNode<'r> + 'a>;
+
+fn create_closure<'a, P: Properties + 'a>(
+    component: FC<P>,
+    raw_props: *const (),
+) -> Rc<dyn for<'r> Fn(&'r Scope) -> VNode<'r>> {
+    // ) -> impl for<'r> Fn(&'r Scope) -> VNode<'r> {
+    let g: Captured = Rc::new(move |scp: &Scope| -> VNode {
+        // cast back into the right lifetime
+        let safe_props: &'_ P = unsafe { &*(raw_props as *const P) };
+        // let ctx: Context<P2> = todo!();
+        let ctx: Context<P> = Context {
+            props: safe_props,
+            scope: scp,
+        };
+
+        let g = component(ctx);
+        let g2 = unsafe { std::mem::transmute(g) };
+        g2
+    });
+    let r: Captured<'static> = unsafe { std::mem::transmute(g) };
+    r
+}
+
 pub struct VFragment<'src> {
     pub key: NodeKey<'src>,
     pub children: &'src [VNode<'src>],
 }
+
+impl<'a> VFragment<'a> {
+    pub fn new(key: Option<&'a str>, children: &'a [VNode<'a>]) -> Self {
+        let key = match key {
+            Some(key) => NodeKey::new(key),
+            None => NodeKey(None),
+        };
+
+        Self { key, children }
+    }
+}

+ 2 - 0
packages/core/src/patch.rs

@@ -146,6 +146,7 @@ pub struct EditMachine<'lock> {
     pub traversal: Traversal,
     next_temporary: u32,
     forcing_new_listeners: bool,
+    pub cur_height: u32,
 
     // // if the current node is a "known" node
     // // any actions that modify this node should update the mapping
@@ -158,6 +159,7 @@ impl<'lock> EditMachine<'lock> {
         Self {
             // current_known: None,
             traversal: Traversal::new(),
+            cur_height: 0,
             next_temporary: 0,
             forcing_new_listeners: false,
             emitter: EditList::<'lock>::default(),

+ 65 - 211
packages/core/src/virtual_dom.rs

@@ -32,6 +32,7 @@ use std::{
     pin::Pin,
     rc::{Rc, Weak},
 };
+pub type ScopeIdx = generational_arena::Index;
 
 /// An integrated virtual node system that progresses events and diffs UI trees.
 /// Differences are converted into patches which a renderer can use to draw the UI.
@@ -52,8 +53,8 @@ pub struct VirtualDom {
 
     /// a strong allocation to the "caller" for the original component and its props
     #[doc(hidden)]
-    _root_caller: Rc<OpaqueComponent<'static>>,
-
+    _root_caller: Rc<OpaqueComponent>,
+    // _root_caller: Rc<OpaqueComponent<'static>>,
     /// Type of the original ctx. This is stored as TypeId so VirtualDom does not need to be generic.
     ///
     /// Whenver props need to be updated, an Error will be thrown if the new props do not
@@ -137,7 +138,8 @@ impl VirtualDom {
 
         // Normally, a component would be passed as a child in the RSX macro which automatically produces OpaqueComponents
         // Here, we need to make it manually, using an RC to force the Weak reference to stick around for the main scope.
-        let _root_caller: Rc<OpaqueComponent<'static>> = Rc::new(move |scope| {
+        let _root_caller: Rc<OpaqueComponent> = Rc::new(move |scope| {
+            // let _root_caller: Rc<OpaqueComponent<'static>> = Rc::new(move |scope| {
             // the lifetime of this closure is just as long as the lifetime on the scope reference
             // this closure moves root props (which is static) into this closure
             let props = unsafe { &*(&root_props as *const _) };
@@ -154,10 +156,11 @@ impl VirtualDom {
         // Make the first scope
         // We don't run the component though, so renderers will need to call "rebuild" when they initialize their DOM
         let link = components.clone();
-        let event_channel = Rc::new(move || {});
+
         let base_scope = components
             .with(|arena| {
                 arena.insert_with(move |myidx| {
+                    let event_channel = _event_queue.new_channel(0, myidx);
                     Scope::new(caller_ref, myidx, None, 0, event_channel, link, &[])
                 })
             })
@@ -175,7 +178,11 @@ impl VirtualDom {
     /// Performs a *full* rebuild of the virtual dom, returning every edit required to generate the actual dom rom scratch
     /// Currently this doesn't do what we want it to do
     pub fn rebuild<'s>(&'s mut self) -> Result<EditList<'s>> {
-        let mut diff_machine = DiffMachine::new();
+        let mut diff_machine = DiffMachine::new(
+            self.components.clone(),
+            self.base_scope,
+            self.event_queue.clone(),
+        );
 
         // Schedule an update and then immediately call it on the root component
         // This is akin to a hook being called from a listener and requring a re-render
@@ -190,10 +197,6 @@ impl VirtualDom {
 
         Ok(diff_machine.consume())
     }
-
-    pub fn base_scope(&self) -> &Scope {
-        todo!()
-    }
 }
 
 // ======================================
@@ -248,7 +251,9 @@ impl VirtualDom {
 
         self.components.try_get_mut(id)?.call_listener(event)?;
 
-        let mut diff_machine = DiffMachine::new();
+        let mut diff_machine =
+            DiffMachine::new(self.components.clone(), id, self.event_queue.clone());
+
         self.progress_completely(&mut diff_machine)?;
 
         Ok(diff_machine.consume())
@@ -263,212 +268,48 @@ impl VirtualDom {
         diff_machine: &'_ mut DiffMachine<'s>,
     ) -> Result<()> {
         // Add this component to the list of components that need to be difed
-        #[allow(unused_assignments)]
-        let mut cur_height: u32 = 0;
+        // #[allow(unused_assignments)]
+        // let mut cur_height: u32 = 0;
 
         // Now, there are events in the queue
-        let mut seen_nodes = HashSet::<ScopeIdx>::new();
         let mut updates = self.event_queue.0.as_ref().borrow_mut();
 
         // Order the nodes by their height, we want the biggest nodes on the top
         // This prevents us from running the same component multiple times
         updates.sort_unstable();
 
+        log::debug!("There are: {:#?} updates to be processed", updates.len());
+
         // Iterate through the triggered nodes (sorted by height) and begin to diff them
         for update in updates.drain(..) {
+            log::debug!("Running updates for: {:#?}", update);
             // Make sure this isn't a node we've already seen, we don't want to double-render anything
             // If we double-renderer something, this would cause memory safety issues
-            if seen_nodes.contains(&update.idx) {
+            if diff_machine.seen_nodes.contains(&update.idx) {
                 continue;
             }
 
             // Now, all the "seen nodes" are nodes that got notified by running this listener
-            seen_nodes.insert(update.idx.clone());
+            diff_machine.seen_nodes.insert(update.idx.clone());
 
             // Start a new mutable borrow to components
             // We are guaranteeed that this scope is unique because we are tracking which nodes have modified
 
             let cur_component = self.components.try_get_mut(update.idx).unwrap();
+            // let inner: &'s mut _ = unsafe { &mut *self.components.0.borrow().arena.get() };
+            // let cur_component = inner.get_mut(update.idx).unwrap();
 
             cur_component.run_scope()?;
 
             diff_machine.diff_node(cur_component.old_frame(), cur_component.next_frame());
 
-            cur_height = cur_component.height;
-
-            log::debug!(
-                "Processing update: {:#?} with height {}",
-                &update.idx,
-                cur_height
-            );
-
-            // Now, the entire subtree has been invalidated. We need to descend depth-first and process
-            // any updates that the diff machine has proprogated into the component lifecycle queue
-            while let Some(event) = diff_machine.lifecycle_events.pop_front() {
-                match event {
-                    // A new component has been computed from the diffing algorithm
-                    // create a new component in the arena, run it, move the diffing machine to this new spot, and then diff it
-                    // this will flood the lifecycle queue with new updates to build up the subtree
-                    LifeCycleEvent::Mount {
-                        caller,
-                        root_id: id,
-                        stable_scope_addr,
-                    } => {
-                        log::debug!("Mounting a new component");
-
-                        // We're modifying the component arena while holding onto references into the assoiated bump arenas of its children
-                        // those references are stable, even if the component arena moves around in memory, thanks to the bump arenas.
-                        // However, there is no way to convey this to rust, so we need to use unsafe to pierce through the lifetime.
-
-                        // Insert a new scope into our component list
-                        let idx = self.components.with(|components| {
-                            components.insert_with(|new_idx| {
-                                let height = cur_height + 1;
-                                Scope::new(
-                                    caller,
-                                    new_idx,
-                                    Some(cur_component.arena_idx),
-                                    height,
-                                    self.event_queue.new_channel(height, new_idx),
-                                    self.components.clone(),
-                                    &[],
-                                )
-                            })
-                        })?;
-
-                        {
-                            let cur_component = self.components.try_get_mut(update.idx).unwrap();
-                            let mut ch = cur_component.descendents.borrow_mut();
-                            ch.insert(idx);
-                            std::mem::drop(ch);
-                        }
-
-                        // Grab out that component
-                        let new_component = self.components.try_get_mut(idx).unwrap();
-
-                        // Actually initialize the caller's slot with the right address
-                        *stable_scope_addr.upgrade().unwrap().as_ref().borrow_mut() = Some(idx);
-
-                        // Run the scope for one iteration to initialize it
-                        new_component.run_scope()?;
-
-                        // Navigate the diff machine to the right point in the output dom
-                        diff_machine.change_list.load_known_root(id);
-
-                        // And then run the diff algorithm
-                        diff_machine
-                            .diff_node(new_component.old_frame(), new_component.next_frame());
-
-                        // Finally, insert this node as a seen node.
-                        seen_nodes.insert(idx);
-                    }
-
-                    // A component has remained in the same location but its properties have changed
-                    // We need to process this component and then dump the output lifecycle events into the queue
-                    LifeCycleEvent::PropsChanged {
-                        caller,
-                        root_id,
-                        stable_scope_addr,
-                    } => {
-                        log::debug!("Updating a component after its props have changed");
-
-                        // Get the stable index to the target component
-                        // This *should* exist due to guarantees in the diff algorithm
-                        let idx = stable_scope_addr
-                            .upgrade()
-                            .unwrap()
-                            .as_ref()
-                            .borrow()
-                            .unwrap();
-
-                        // Grab out that component
-                        let component = self.components.try_get_mut(idx).unwrap();
-
-                        // We have to move the caller over or running the scope will fail
-                        component.update_caller(caller);
-
-                        // Run the scope
-                        component.run_scope()?;
-
-                        // Navigate the diff machine to the right point in the output dom
-                        diff_machine.change_list.load_known_root(root_id);
-
-                        // And then run the diff algorithm
-                        diff_machine.diff_node(component.old_frame(), component.next_frame());
-
-                        // Finally, insert this node as a seen node.
-                        seen_nodes.insert(idx);
-                    }
-
-                    // A component's parent has updated, but its properties did not change.
-                    // This means the caller ptr is invalidated and needs to be updated, but the component itself does not need to be re-ran
-                    LifeCycleEvent::SameProps {
-                        caller,
-                        stable_scope_addr,
-                        ..
-                    } => {
-                        // In this case, the parent made a new VNode that resulted in the same props for us
-                        // However, since our caller is located in a Bump frame, we need to update the caller pointer (which is now invalid)
-                        log::debug!("Received the same props");
-
-                        // Get the stable index to the target component
-                        // This *should* exist due to guarantees in the diff algorithm
-                        let idx = stable_scope_addr
-                            .upgrade()
-                            .unwrap()
-                            .as_ref()
-                            .borrow()
-                            .unwrap();
-
-                        // Grab out that component
-                        let component = self.components.try_get_mut(idx).unwrap();
-
-                        // We have to move the caller over or running the scope will fail
-                        component.update_caller(caller);
-
-                        // This time, we will not add it to our seen nodes since we did not actually run it
-                    }
-
-                    LifeCycleEvent::Remove {
-                        root_id,
-                        stable_scope_addr,
-                    } => {
-                        let id = stable_scope_addr
-                            .upgrade()
-                            .unwrap()
-                            .as_ref()
-                            .borrow()
-                            .unwrap();
-
-                        log::warn!("Removing node {:#?}", id);
-
-                        // This would normally be recursive but makes sense to do linear to
-                        let mut children_to_remove = VecDeque::new();
-                        children_to_remove.push_back(id);
-
-                        // Accumulate all the child components that need to be removed
-                        while let Some(child_id) = children_to_remove.pop_back() {
-                            let comp = self.components.try_get(child_id).unwrap();
-                            let children = comp.descendents.borrow();
-                            for child in children.iter() {
-                                children_to_remove.push_front(*child);
-                            }
-                            log::debug!("Removing component: {:#?}", child_id);
-                            self.components
-                                .with(|components| components.remove(child_id).unwrap())
-                                .unwrap();
-                        }
-                    }
+            // cur_height = cur_component.height;
 
-                    LifeCycleEvent::Replace {
-                        caller,
-                        root_id: id,
-                        ..
-                    } => {
-                        unimplemented!("This feature (Replace) is unimplemented")
-                    }
-                }
-            }
+            // log::debug!(
+            //     "Processing update: {:#?} with height {}",
+            //     &update.idx,
+            //     cur_height
+            // );
         }
 
         Ok(())
@@ -492,7 +333,7 @@ pub struct Scope {
 
     // IDs of children that this scope has created
     // This enables us to drop the children and their children when this scope is destroyed
-    descendents: RefCell<HashSet<ScopeIdx>>,
+    pub(crate) descendents: RefCell<HashSet<ScopeIdx>>,
 
     child_nodes: &'static [VNode<'static>],
 
@@ -510,8 +351,8 @@ pub struct Scope {
     pub event_channel: Rc<dyn Fn() + 'static>,
 
     // pub event_queue: EventQueue,
-    pub caller: Weak<OpaqueComponent<'static>>,
-
+    pub caller: Weak<OpaqueComponent>,
+    // pub caller: Weak<OpaqueComponent<'static>>,
     pub hookidx: RefCell<usize>,
 
     // ==========================
@@ -545,8 +386,9 @@ impl Scope {
     //
     // Scopes cannot be made anywhere else except for this file
     // Therefore, their lifetimes are connected exclusively to the virtual dom
-    fn new<'creator_node>(
-        caller: Weak<OpaqueComponent<'creator_node>>,
+    pub fn new<'creator_node>(
+        caller: Weak<OpaqueComponent>,
+        // caller: Weak<OpaqueComponent<'creator_node>>,
         arena_idx: ScopeIdx,
         parent: Option<ScopeIdx>,
         height: u32,
@@ -572,13 +414,17 @@ impl Scope {
         // Not the best solution, so TODO on removing this in favor of a dedicated resource abstraction.
         let caller = unsafe {
             std::mem::transmute::<
-                Weak<OpaqueComponent<'creator_node>>,
-                Weak<OpaqueComponent<'static>>,
+                Weak<OpaqueComponent>,
+                Weak<OpaqueComponent>,
+                // Weak<OpaqueComponent<'creator_node>>,
+                // Weak<OpaqueComponent<'static>>,
             >(caller)
         };
 
+        let child_nodes = unsafe { std::mem::transmute(child_nodes) };
+
         Self {
-            child_nodes: &[],
+            child_nodes: child_nodes,
             caller,
             parent,
             arena_idx,
@@ -594,11 +440,14 @@ impl Scope {
         }
     }
 
-    pub fn update_caller<'creator_node>(&mut self, caller: Weak<OpaqueComponent<'creator_node>>) {
+    pub fn update_caller<'creator_node>(&mut self, caller: Weak<OpaqueComponent>) {
+        // pub fn update_caller<'creator_node>(&mut self, caller: Weak<OpaqueComponent<'creator_node>>) {
         let broken_caller = unsafe {
             std::mem::transmute::<
-                Weak<OpaqueComponent<'creator_node>>,
-                Weak<OpaqueComponent<'static>>,
+                Weak<OpaqueComponent>,
+                Weak<OpaqueComponent>,
+                // Weak<OpaqueComponent<'creator_node>>,
+                // Weak<OpaqueComponent<'static>>,
             >(caller)
         };
 
@@ -630,8 +479,10 @@ impl Scope {
             .ok_or(Error::FatalInternal("Failed to get caller"))?;
 
         // Cast the caller ptr from static to one with our own reference
-        let c2: &OpaqueComponent<'static> = caller.as_ref();
-        let c3: &OpaqueComponent<'sel> = unsafe { std::mem::transmute(c2) };
+        let c2: &OpaqueComponent = caller.as_ref();
+        let c3: &OpaqueComponent = unsafe { std::mem::transmute(c2) };
+        // let c2: &OpaqueComponent<'static> = caller.as_ref();
+        // let c3: &OpaqueComponent<'sel> = unsafe { std::mem::transmute(c2) };
 
         let unsafe_head = unsafe { self.own_vnodes(c3) };
 
@@ -641,7 +492,7 @@ impl Scope {
     }
 
     // this is its own function so we can preciesly control how lifetimes flow
-    unsafe fn own_vnodes<'a>(&'a self, f: &OpaqueComponent<'a>) -> VNode<'static> {
+    unsafe fn own_vnodes<'a>(&'a self, f: &OpaqueComponent) -> VNode<'static> {
         let new_head: VNode<'a> = f(self);
         let out: VNode<'static> = std::mem::transmute(new_head);
         out
@@ -959,22 +810,25 @@ Any function prefixed with "use" should not be called conditionally.
 
 // We actually allocate the properties for components in their parent's properties
 // We then expose a handle to use those props for render in the form of "OpaqueComponent"
-pub(crate) type OpaqueComponent<'e> = dyn for<'b> Fn(&'b Scope) -> VNode<'b> + 'e;
+pub type OpaqueComponent = dyn for<'b> Fn(&'b Scope) -> VNode<'b>;
 
 #[derive(PartialEq, Debug, Clone, Default)]
-pub(crate) struct EventQueue(pub Rc<RefCell<Vec<HeightMarker>>>);
+pub struct EventQueue(pub Rc<RefCell<Vec<HeightMarker>>>);
 
 impl EventQueue {
     pub fn new_channel(&self, height: u32, idx: ScopeIdx) -> Rc<dyn Fn()> {
         let inner = self.clone();
         let marker = HeightMarker { height, idx };
-        Rc::new(move || inner.0.as_ref().borrow_mut().push(marker))
+        Rc::new(move || {
+            log::debug!("channel updated {:#?}", marker);
+            inner.0.as_ref().borrow_mut().push(marker)
+        })
     }
 }
 
 /// A helper type that lets scopes be ordered by their height
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub(crate) struct HeightMarker {
+pub struct HeightMarker {
     pub idx: ScopeIdx,
     pub height: u32,
 }
@@ -1050,20 +904,20 @@ impl ActiveFrame {
         )
     }
 
-    fn from_frames(a: BumpFrame, b: BumpFrame) -> Self {
+    pub fn from_frames(a: BumpFrame, b: BumpFrame) -> Self {
         Self {
             generation: 0.into(),
             frames: [a, b],
         }
     }
 
-    fn cur_frame(&self) -> &BumpFrame {
+    pub fn cur_frame(&self) -> &BumpFrame {
         match *self.generation.borrow() & 1 == 0 {
             true => &self.frames[0],
             false => &self.frames[1],
         }
     }
-    fn cur_frame_mut(&mut self) -> &mut BumpFrame {
+    pub fn cur_frame_mut(&mut self) -> &mut BumpFrame {
         match *self.generation.borrow() & 1 == 0 {
             true => &mut self.frames[0],
             false => &mut self.frames[1],
@@ -1098,7 +952,7 @@ impl ActiveFrame {
         }
     }
 
-    fn next(&mut self) -> &mut BumpFrame {
+    pub fn next(&mut self) -> &mut BumpFrame {
         *self.generation.borrow_mut() += 1;
 
         if *self.generation.borrow() % 2 == 0 {

+ 1 - 1
packages/hooks/src/lib.rs

@@ -84,7 +84,7 @@ fn use_map() {}
 // Elements are received as Rc<T> in case the underlying collection is shuffled around
 // Setters/getters can be generated
 fn use_collection<'a, T: Collection>(
-    ctx: &Context<'a>,
+    ctx: &impl Scoped<'a>,
     f: impl Fn() -> T,
 ) -> CollectionHandle<'a, T> {
     ctx.use_hook(

+ 1 - 1
packages/recoil/examples/callback.rs

@@ -20,7 +20,7 @@ fn update_title(api: &RecoilApi) {
 }
 
 static App: FC<()> = |ctx| {
-    let title = use_read(ctx, &TITLE);
+    let title = use_read(&ctx, &TITLE);
     let next_light = use_recoil_api(ctx, |api| move |_| update_title(&api));
 
     rsx! { in ctx,

+ 15 - 18
packages/recoil/src/lib.rs

@@ -32,7 +32,7 @@ mod traits {
     // Atoms, selectors, and their family variants are readable
     pub trait Readable<T: AtomValue>: Sized + Copy {
         fn use_read<'a, P: 'static>(self, ctx: Context<'a, P>) -> &'a T {
-            hooks::use_read(ctx, self)
+            hooks::use_read(&ctx, self)
         }
 
         // This returns a future of the value
@@ -95,9 +95,9 @@ mod atoms {
             const EXAMPLE_ATOM: Atom<i32> = |_| 10;
 
             // ensure that atoms are both read and write
-            let _ = use_read(ctx, &EXAMPLE_ATOM);
-            let _ = use_read_write(ctx, &EXAMPLE_ATOM);
-            let _ = use_write(ctx, &EXAMPLE_ATOM);
+            let _ = use_read(&ctx, &EXAMPLE_ATOM);
+            let _ = use_read_write(&ctx, &EXAMPLE_ATOM);
+            let _ = use_write(&ctx, &EXAMPLE_ATOM);
         }
     }
 }
@@ -161,7 +161,7 @@ mod atomfamily {
 
         fn test(ctx: Context<()>) {
             let title = Titles.select(&10).use_read(ctx);
-            let t2 = use_read(ctx, &Titles.select(&10));
+            let t2 = use_read(&ctx, &Titles.select(&10));
         }
     }
 }
@@ -368,7 +368,7 @@ mod root {
 
 mod hooks {
     use super::*;
-    use dioxus_core::{hooks::use_ref, prelude::Context};
+    use dioxus_core::{hooks::use_ref, prelude::Context, virtual_dom::Scoped};
 
     pub fn use_init_recoil_root<P>(ctx: Context<P>, cfg: impl Fn(())) {
         ctx.use_create_context(move || RefCell::new(RecoilRoot::new()))
@@ -381,12 +381,12 @@ mod hooks {
     ///
     /// You can use this method to create controllers that perform much more complex actions than set/get
     /// However, be aware that "getting" values through this hook will not subscribe the component to any updates.
-    pub fn use_recoil_api<'a, P>(ctx: Context<'a, P>) -> &Rc<RecoilContext> {
+    pub fn use_recoil_api<'a>(ctx: &impl Scoped<'a>) -> &'a Rc<RecoilContext> {
         ctx.use_context::<RecoilContext>()
     }
 
-    pub fn use_write<'a, T: AtomValue, P>(
-        ctx: Context<'a, P>,
+    pub fn use_write<'a, T: AtomValue>(
+        ctx: &impl Scoped<'a>,
         // todo: this shouldn't need to be static
         writable: impl Writable<T>,
     ) -> &'a Rc<dyn Fn(T)> {
@@ -412,10 +412,10 @@ mod hooks {
     /// Read the atom and get the Rc directly to the Atom's slot
     /// This is useful if you need the memoized Atom value. However, Rc<T> is not as easy to
     /// work with as
-    pub fn use_read_raw<'a, T: AtomValue, P: 'static>(
-        ctx: Context<'a, P>,
+    pub fn use_read_raw<'a, T: AtomValue>(
+        ctx: &impl Scoped<'a>,
         readable: impl Readable<T>,
-    ) -> &Rc<T> {
+    ) -> &'a Rc<T> {
         struct ReadHook<T> {
             value: Rc<T>,
             consumer_id: u32,
@@ -449,10 +449,7 @@ mod hooks {
     }
 
     ///
-    pub fn use_read<'a, T: AtomValue, P: 'static>(
-        ctx: Context<'a, P>,
-        readable: impl Readable<T>,
-    ) -> &'a T {
+    pub fn use_read<'a, T: AtomValue>(ctx: &impl Scoped<'a>, readable: impl Readable<T>) -> &'a T {
         use_read_raw(ctx, readable).as_ref()
     }
 
@@ -471,8 +468,8 @@ mod hooks {
     /// // equivalent to:
     /// let (title, set_title) = (use_read(ctx, &Title), use_write(ctx, &Title));
     /// ```
-    pub fn use_read_write<'a, T: AtomValue + 'static, P: 'static>(
-        ctx: Context<'a, P>,
+    pub fn use_read_write<'a, T: AtomValue + 'static>(
+        ctx: &impl Scoped<'a>,
         writable: impl Writable<T>,
     ) -> (&'a T, &'a Rc<dyn Fn(T)>) {
         (use_read(ctx, writable), use_write(ctx, writable))

+ 36 - 0
packages/web/examples/children.rs

@@ -0,0 +1,36 @@
+//! Basic example that renders a simple VNode to the browser.
+
+use dioxus_core::prelude::*;
+use dioxus_web::*;
+
+fn main() {
+    // Setup logging
+    wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
+    console_error_panic_hook::set_once();
+
+    // Run the app
+    wasm_bindgen_futures::spawn_local(WebsysRenderer::start(App));
+}
+
+static App: FC<()> = |ctx| {
+    ctx.render(rsx! {
+        Calcier {
+            h2 {"abc 1"}
+            h2 {"abc 2"}
+            h2 {"abc 3"}
+            h2 {"abc 4"}
+            h2 {"abc 5"}
+        }
+    })
+};
+
+static Calcier: FC<()> = |ctx| {
+    ctx.render(rsx! {
+        div {
+            h1 {
+                "abc 0"
+            }
+            {ctx.children()}
+        }
+    })
+};

+ 1 - 1
packages/web/examples/context.rs

@@ -52,7 +52,7 @@ struct ButtonProps {
     id: u8,
 }
 
-fn CustomButton(ctx: Context, props: &ButtonProps) -> VNode {
+fn CustomButton(ctx: Context<ButtonProps>) -> VNode {
     let names = ctx.use_context::<CustomContext>();
     let name = names.0[ctx.id as usize];
 

+ 25 - 0
packages/web/examples/fragment.rs

@@ -0,0 +1,25 @@
+//! Basic example that renders a simple VNode to the browser.
+
+use dioxus_core::prelude::*;
+use dioxus_web::*;
+
+fn main() {
+    // Setup logging
+    wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
+    console_error_panic_hook::set_once();
+
+    // Run the app
+    wasm_bindgen_futures::spawn_local(WebsysRenderer::start(App));
+}
+
+static App: FC<()> = |ctx| {
+    ctx.render(rsx! {
+        h2 { "abc 1" }
+        div {
+            "hello world!"
+        }
+        Fragment {
+            h2 { "abc 2"}
+        }
+    })
+};

+ 11 - 0
packages/web/examples/helloworld.rs

@@ -0,0 +1,11 @@
+use dioxus_web::prelude::*;
+
+fn main() {
+    wasm_bindgen_futures::spawn_local(dioxus_web::WebsysRenderer::start(App))
+}
+
+fn App(ctx: Context<()>) -> VNode {
+    ctx.render(rsx! {
+        div { "Hello, world!" }
+    })
+}

+ 21 - 0
packages/web/examples/many.rs

@@ -0,0 +1,21 @@
+use dioxus_core::prelude::*;
+use dioxus_web::WebsysRenderer;
+
+fn main() {
+    wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
+    console_error_panic_hook::set_once();
+
+    log::info!("hello world");
+    wasm_bindgen_futures::spawn_local(WebsysRenderer::start(Example));
+}
+
+static Example: FC<()> = |ctx| {
+    ctx.render(rsx! {
+        div {
+            span {
+                class: "px-2 py-1 flex w-36 mt-4 items-center text-xs rounded-md font-semibold text-yellow-500 bg-yellow-100"
+                "DUE DATE : 18 JUN"
+            }
+        }
+    })
+};

+ 2 - 2
packages/web/examples/rsxt.rs

@@ -53,7 +53,7 @@ struct ButtonProps<'src, F: Fn(MouseEvent)> {
     handler: F
 }
 
-fn CustomButton<'b, 'a, F: Fn(MouseEvent)>(ctx: Context<'a>, props: &'b ButtonProps<'b, F>) -> VNode {
+fn CustomButton<'a, F: Fn(MouseEvent)>(ctx: Context<'a, ButtonProps<'a, F>>) -> VNode {
     ctx.render(rsx!{
         button {  
             class: "inline-block py-4 px-8 mr-6 leading-none text-white bg-indigo-600 hover:bg-indigo-900 font-semibold rounded shadow"
@@ -74,7 +74,7 @@ impl<F: Fn(MouseEvent)> PartialEq for ButtonProps<'_, F> {
 struct PlaceholderProps {
     val: &'static str
 }
-fn Placeholder(ctx: Context, props: &PlaceholderProps) -> VNode {
+fn Placeholder(ctx: Context<PlaceholderProps>) -> VNode {
     ctx.render(rsx!{
         div {
             "child: {ctx.val}"

+ 5 - 6
packages/web/examples/todomvcsingle.rs

@@ -149,11 +149,11 @@ pub fn FilterToggles(ctx: Context<()>) -> VNode {
     .iter()
     .map(|(name, path, filter)| {
         rsx!(
-            li {
-                class: "{name}"
-                a { "{name}",
+            li { class: "{name}"
+                a {
                     href: "{path}",
                     onclick: move |_| reducer.set_filter(&filter),
+                    "{name}",
                 }
             }
         )
@@ -168,7 +168,7 @@ pub fn FilterToggles(ctx: Context<()>) -> VNode {
         footer {
             span {
                 strong {"{items_left}"}
-                span {"{item_text} left"}
+                span { "{item_text} left" }
             }
             ul {
                 class: "filters"
@@ -180,8 +180,7 @@ pub fn FilterToggles(ctx: Context<()>) -> VNode {
 
 pub fn Footer(ctx: Context<()>) -> VNode {
     rsx! { in ctx,
-        footer {
-            class: "info"
+        footer { class: "info"
             p {"Double-click to edit a todo"}
             p {
                 "Created by "