diff --git a/Cargo.toml b/Cargo.toml index b60a8635ff..7958e351d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "packages/perseus-actix-web", "packages/perseus-cli", # TODO remake showcase app for CLI + "examples/showcase", # "examples/showcase/app", # "examples/showcase/server-actix-web", "examples/cli", diff --git a/examples/README.md b/examples/README.md index 69763fbdb6..780ad2146d 100644 --- a/examples/README.md +++ b/examples/README.md @@ -4,20 +4,7 @@ This folder contains examples for Perseus, which are used to test the project an These examples are all fully self-contained, and do not serve as examples in the traditional Cargo way, they are each indepedent crates to enable the use of build tools such as `wasm-pack`. -## Workspaces?? - -A Perseus setup is composed of an app and a server, which would normally be in a workspace project. However, examples with their own `Cargo.toml` manifests aren't detected by RLS, and so we need to make them part of the super-workspace at the root. The problem with that is that then we'd have nested workspaces, which are currently impossible. The solution used is to have each example be atomic (i.e. app OR server), but they're still listed together under the same parent directory. If you want to clone one of these to run locally without the rest of the repo, you'll need to get the appropriate directory with both an app and a server, and then add a new `Cargo.toml` at the root of that with the following contents: - -```toml -[workspace] -members = [ - "app", - "server" -] -``` - -All (non-CLI) examples should have both an `app` and a `server` directory. - -- Showcase -- an app that demonstrates all the different features of Perseus, including SSR, SSG, and ISR (this example is actively used for testing) +- Showcase -- an app that demonstrates all the different features of Perseus, including SSR, SSG, and ISR (this example is actively used for testing/development) - Basic -- a simple app that uses the Perseus CLI (symlinks to CLI example) - CLI -- same as basic, but includes the CLI subcrates (actively used for testing/development) +- i18n -- a simple app that showcases internationalization in particular diff --git a/examples/basic/Cargo.toml b/examples/basic/Cargo.toml index a4d2f1fedd..d6a230f35d 100644 --- a/examples/basic/Cargo.toml +++ b/examples/basic/Cargo.toml @@ -10,8 +10,8 @@ edition = "2018" [dependencies] perseus = { path = "../../packages/perseus" } -sycamore = { version = "0.5.1", features = ["ssr"] } -sycamore-router = "0.5.1" +sycamore = { version = "0.5", features = ["ssr"] } +sycamore-router = "0.5" serde = { version = "1", features = ["derive"] } serde_json = "1" # Possibly don't need? diff --git a/examples/cli/.perseus/Cargo.toml b/examples/cli/.perseus/Cargo.toml index d1deb10d66..a645dad1e6 100644 --- a/examples/cli/.perseus/Cargo.toml +++ b/examples/cli/.perseus/Cargo.toml @@ -13,8 +13,8 @@ edition = "2018" app = { package = "perseus-example-cli", path = "../" } perseus = { path = "../../../packages/perseus" } -sycamore = { version = "0.5.1", features = ["ssr"] } -sycamore-router = "0.5.1" +sycamore = { version = "0.5", features = ["ssr"] } +sycamore-router = "0.5" web-sys = { version = "0.3", features = ["Headers", "Request", "RequestInit", "RequestMode", "Response", "ReadableStream", "Window"] } wasm-bindgen = { version = "0.2", features = ["serde-serialize"] } serde = { version = "1", features = ["derive"] } diff --git a/examples/cli/Cargo.toml b/examples/cli/Cargo.toml index aacdb68ce9..6930325f1f 100644 --- a/examples/cli/Cargo.toml +++ b/examples/cli/Cargo.toml @@ -10,8 +10,8 @@ edition = "2018" [dependencies] perseus = { path = "../../packages/perseus" } -sycamore = { version = "0.5.1", features = ["ssr"] } -sycamore-router = "0.5.1" +sycamore = { version = "0.5", features = ["ssr"] } +sycamore-router = "0.5" serde = { version = "1", features = ["derive"] } serde_json = "1" # Possibly don't need? diff --git a/examples/i18n/Cargo.toml b/examples/i18n/Cargo.toml index 1879909876..2aaf0ea918 100644 --- a/examples/i18n/Cargo.toml +++ b/examples/i18n/Cargo.toml @@ -9,8 +9,8 @@ edition = "2018" # Perseus itself, which we (amazingly) need for a Perseus app perseus = { path = "../../packages/perseus" } # Sycamore, the library Perseus depends on for lower-leve reactivity primitivity -sycamore = { version = "0.5.1", features = ["ssr"] } -sycamore-router = "0.5.1" +sycamore = { version = "0.5", features = ["ssr"] } +sycamore-router = "0.5" # Serde, which lets you work with representations of data, like JSON serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/examples/showcase/.gitignore b/examples/showcase/.gitignore index 57a7f51c89..4c35bb063c 100644 --- a/examples/showcase/.gitignore +++ b/examples/showcase/.gitignore @@ -1,4 +1,3 @@ -target/ -Cargo.lock -dist/ -pkg/ \ No newline at end of file +/target + +.perseus/ diff --git a/examples/showcase/Cargo.toml b/examples/showcase/Cargo.toml new file mode 100644 index 0000000000..9c0d8b216f --- /dev/null +++ b/examples/showcase/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "perseus-example-showcase" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +# Perseus itself, which we (amazingly) need for a Perseus app +perseus = { path = "../../packages/perseus" } +# Sycamore, the library Perseus depends on for lower-leve reactivity primitivity +sycamore = { version = "0.5", features = ["ssr"] } +sycamore-router = "0.5" +# Serde, which lets you work with representations of data, like JSON +serde = { version = "1", features = ["derive"] } +serde_json = "1" + +urlencoding = "2.1" diff --git a/examples/showcase/app/Cargo.toml b/examples/showcase/app/Cargo.toml deleted file mode 100644 index f1e84b228d..0000000000 --- a/examples/showcase/app/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "perseus-showcase-app" -version = "0.1.2" -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -perseus = { path = "../../../packages/perseus" } -sycamore = { version = "0.5.1", features = ["ssr"] } -sycamore-router = "0.5.1" -web-sys = { version = "0.3", features = ["Headers", "Request", "RequestInit", "RequestMode", "Response", "ReadableStream", "Window"] } -wasm-bindgen = { version = "0.2", features = ["serde-serialize"] } -serde = { version = "1", features = ["derive"] } -serde_json = "1" # Possibly don't need? -console_error_panic_hook = "0.1.6" -urlencoding = "2.1" -futures = "0.3" - -# This section is needed for WASM Pack (which we use instead of Trunk for flexibility) -[lib] -crate-type = ["cdylib", "rlib"] - -[[bin]] -name = "ssg" -path = "src/bin/build.rs" diff --git a/examples/showcase/app/main.js b/examples/showcase/app/main.js deleted file mode 100644 index 026af258c6..0000000000 --- a/examples/showcase/app/main.js +++ /dev/null @@ -1,6 +0,0 @@ -import init, { run } from "./pkg/perseus_showcase_app.js"; -async function main() { - await init("/.perseus/bundle.wasm"); - run(); -} -main(); diff --git a/examples/showcase/app/src/bin/build.rs b/examples/showcase/app/src/bin/build.rs deleted file mode 100644 index 78c10f85ee..0000000000 --- a/examples/showcase/app/src/bin/build.rs +++ /dev/null @@ -1,25 +0,0 @@ -use futures::executor::block_on; -use perseus::{build_templates_for_locale, FsConfigManager, SsrNode, Translator}; -use perseus_showcase_app::pages; - -fn main() { - let config_manager = FsConfigManager::new("./dist".to_string()); - - let fut = build_templates_for_locale( - vec![ - pages::index::get_page::(), - pages::about::get_page::(), - pages::post::get_page::(), - pages::new_post::get_page::(), - pages::ip::get_page::(), - pages::time::get_page::(), - pages::time_root::get_page::(), - pages::amalgamation::get_page::(), - ], - Translator::empty(), - &config_manager, - ); - block_on(fut).expect("Static generation failed!"); - - println!("Static generation successfully completed!"); -} diff --git a/examples/showcase/app/src/lib.rs b/examples/showcase/app/src/lib.rs deleted file mode 100644 index ac6e71bea8..0000000000 --- a/examples/showcase/app/src/lib.rs +++ /dev/null @@ -1,127 +0,0 @@ -pub mod pages; - -use perseus::{app_shell, ErrorPages}; -use sycamore::prelude::*; -use sycamore_router::{BrowserRouter, Route}; -use wasm_bindgen::prelude::*; - -// Define our routes -#[derive(Route)] -enum AppRoute { - #[to("/")] - Index, - #[to("/about")] - About, - #[to("/post/new")] - NewPost, - #[to("/post/")] - Post { slug: Vec }, - #[to("/ip")] - Ip, - #[to("/time")] - TimeRoot, - #[to("/timeisr/")] - Time { slug: String }, - #[to("/amalgamation")] - Amalgamation, - #[not_found] - NotFound, -} - -fn get_error_pages() -> ErrorPages { - let mut error_pages = ErrorPages::new(Box::new(|_, _, _| { - template! { - p { "Another error occurred." } - } - })); - error_pages.add_page( - 404, - Box::new(|_, _, _| { - template! { - p { "Page not found." } - } - }), - ); - error_pages.add_page( - 400, - Box::new(|_, _, _| { - template! { - p { "Client error occurred..." } - } - }), - ); - - error_pages -} - -// This is deliberately purely client-side rendered -#[wasm_bindgen] -pub fn run() -> Result<(), JsValue> { - std::panic::set_hook(Box::new(console_error_panic_hook::hook)); - // Get the root (for the router) we'll be injecting page content into - let root = web_sys::window() - .unwrap() - .document() - .unwrap() - .query_selector("#_perseus_root") - .unwrap() - .unwrap(); - - sycamore::render_to( - || { - template! { - BrowserRouter(|route: AppRoute| { - // TODO improve performance rather than naively copying error pages for every template - match route { - AppRoute::Index => app_shell( - "index".to_string(), - pages::index::template_fn(), - get_error_pages() - ), - AppRoute::About => app_shell( - "about".to_string(), - pages::about::template_fn(), - get_error_pages() - ), - AppRoute::Post { slug } => app_shell( - format!("post/{}", slug.join("/")), - pages::post::template_fn(), - get_error_pages() - ), - AppRoute::NewPost => app_shell( - "post/new".to_string(), - pages::new_post::template_fn(), - get_error_pages() - ), - AppRoute::Ip => app_shell( - "ip".to_string(), - pages::ip::template_fn(), - get_error_pages() - ), - AppRoute::Time { slug } => app_shell( - format!("timeisr/{}", slug), - pages::time::template_fn(), - get_error_pages() - ), - AppRoute::TimeRoot => app_shell( - "time".to_string(), - pages::time_root::template_fn(), - get_error_pages() - ), - AppRoute::Amalgamation => app_shell( - "amalgamation".to_string(), - pages::amalgamation::template_fn(), - get_error_pages() - ), - AppRoute::NotFound => template! { - p {"Not Found."} - } - } - }) - } - }, - &root, - ); - - Ok(()) -} diff --git a/examples/showcase/app/src/pages/mod.rs b/examples/showcase/app/src/pages/mod.rs deleted file mode 100644 index 1c3610ee19..0000000000 --- a/examples/showcase/app/src/pages/mod.rs +++ /dev/null @@ -1,26 +0,0 @@ -pub mod about; -pub mod amalgamation; -pub mod index; -pub mod ip; -pub mod new_post; -pub mod post; -pub mod time; -pub mod time_root; - -use perseus::{get_templates_map, Template}; -use std::collections::HashMap; -use sycamore::prelude::GenericNode; - -/// Shorthand for the `get_templates_map!` macro from Perseus for our specific app pages. -pub fn get_templates_map() -> HashMap> { - get_templates_map![ - index::get_page::(), - about::get_page::(), - post::get_page::(), - new_post::get_page::(), - ip::get_page::(), - time::get_page::(), - time_root::get_page::(), - amalgamation::get_page::() - ] -} diff --git a/examples/showcase/bonnie.toml b/examples/showcase/bonnie.toml deleted file mode 100644 index 1dae7d15fb..0000000000 --- a/examples/showcase/bonnie.toml +++ /dev/null @@ -1,19 +0,0 @@ -version="0.3.1" - -[scripts] -clean = "rm -f ./app/dist/static/*" -build.cmd = [ - "cd app", - "cargo run --bin ssg", - "wasm-pack build --target web", - "rollup ./main.js --format iife --file ./pkg/bundle.js" -] -build.subcommands.--watch = [ - "bonnie clean", - "find ../../ -not -path \"../../target/*\" -not -path \"../../.git/*\" -not -path \"../../examples/showcase/app/dist/*\" | entr -s \"bonnie build\"" -] -serve.cmd = [ - "cd server-%server", - "cargo watch -w ../../../ -x \"run\"" -] -serve.args = [ "server" ] \ No newline at end of file diff --git a/examples/showcase/app/index.html b/examples/showcase/index.html similarity index 73% rename from examples/showcase/app/index.html rename to examples/showcase/index.html index 2b1a3ffa66..45e62a9131 100644 --- a/examples/showcase/app/index.html +++ b/examples/showcase/index.html @@ -4,10 +4,11 @@ - Perseus Starter App + Perseus Showcase App + -
+
diff --git a/examples/showcase/server-actix-web/Cargo.toml b/examples/showcase/server-actix-web/Cargo.toml deleted file mode 100644 index 6cf277e5c6..0000000000 --- a/examples/showcase/server-actix-web/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "perseus-showcase-server-actix-web" -version = "0.1.2" -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -perseus = { path = "../../../packages/perseus" } -perseus-actix-web = { path = "../../../packages/perseus-actix-web" } -actix-web = "3.3" -actix-files = "0.5" -urlencoding = "2.1" -serde_json = "1" -sycamore = { version = "0.5.1", features = ["ssr"] } -perseus-showcase-app = { path = "../app" } -futures = "0.3" diff --git a/examples/showcase/server-actix-web/src/main.rs b/examples/showcase/server-actix-web/src/main.rs deleted file mode 100644 index cc0ddb65b0..0000000000 --- a/examples/showcase/server-actix-web/src/main.rs +++ /dev/null @@ -1,23 +0,0 @@ -use actix_web::{App, HttpServer}; -use futures::executor::block_on; -use perseus::{FsConfigManager, SsrNode}; -use perseus_actix_web::{configurer, Options}; -use perseus_showcase_app::pages; - -#[actix_web::main] -async fn main() -> std::io::Result<()> { - HttpServer::new(|| { - App::new().configure(block_on(configurer( - Options { - index: "../app/index.html".to_string(), - js_bundle: "../app/pkg/bundle.js".to_string(), - wasm_bundle: "../app/pkg/perseus_showcase_app_bg.wasm".to_string(), - templates_map: pages::get_templates_map::(), - }, - FsConfigManager::new("../app/dist".to_string()), - ))) - }) - .bind(("localhost", 8080))? - .run() - .await -} diff --git a/examples/showcase/src/error_pages.rs b/examples/showcase/src/error_pages.rs new file mode 100644 index 0000000000..5f0cf4dc59 --- /dev/null +++ b/examples/showcase/src/error_pages.rs @@ -0,0 +1,28 @@ +use perseus::ErrorPages; +use sycamore::template; + +pub fn get_error_pages() -> ErrorPages { + let mut error_pages = ErrorPages::new(Box::new(|_, _, _, _| { + template! { + p { "Another error occurred." } + } + })); + error_pages.add_page( + 404, + Box::new(|_, _, _, _| { + template! { + p { "Page not found." } + } + }), + ); + error_pages.add_page( + 400, + Box::new(|_, _, _, _| { + template! { + p { "Client error occurred..." } + } + }), + ); + + error_pages +} diff --git a/examples/showcase/src/lib.rs b/examples/showcase/src/lib.rs new file mode 100644 index 0000000000..ca3a9dd7a1 --- /dev/null +++ b/examples/showcase/src/lib.rs @@ -0,0 +1,89 @@ +mod error_pages; +mod templates; + +use perseus::define_app; + +#[derive(perseus::Route)] +pub enum Route { + #[to("/")] + Index { locale: String }, + #[to("//about")] + About { locale: String }, + #[to("//post/new")] + NewPost { locale: String }, + // BUG: Sycamore doesn't support dynamic paths before dynamic segments (https://github.com/sycamore-rs/sycamore/issues/228) + #[to("/post/")] + Post { slug: Vec }, + #[to("//ip")] + Ip { locale: String }, + #[to("//time")] + TimeRoot { locale: String }, + #[to("//timeisr/")] + Time { locale: String, slug: String }, + #[to("//amalgamation")] + Amalgamation { locale: String }, + #[not_found] + NotFound, +} + +define_app! { + root: "#root", + route: Route, + router: { + Route::Index { locale } => [ + "index".to_string(), + templates::index::template_fn(), + locale + ], + Route::About { locale } => [ + "about".to_string(), + templates::about::template_fn(), + locale + ], + Route::Post { slug } => [ + format!("post/{}", slug.join("/")), + templates::post::template_fn(), + "en-US".to_string() // BUG: see above + ], + Route::NewPost { locale } => [ + "post/new".to_string(), + templates::new_post::template_fn(), + locale + ], + Route::Ip { locale } => [ + "ip".to_string(), + templates::ip::template_fn(), + locale + ], + Route::Time { slug, locale } => [ + format!("timeisr/{}", slug), + templates::time::template_fn(), + locale + ], + Route::TimeRoot { locale } => [ + "time".to_string(), + templates::time_root::template_fn(), + locale + ], + Route::Amalgamation { locale } => [ + "amalgamation".to_string(), + templates::amalgamation::template_fn(), + locale + ] + }, + error_pages: crate::error_pages::get_error_pages(), + templates: [ + crate::templates::index::get_template::(), + crate::templates::about::get_template::(), + crate::templates::post::get_template::(), + crate::templates::new_post::get_template::(), + crate::templates::ip::get_template::(), + crate::templates::time::get_template::(), + crate::templates::time_root::get_template::(), + crate::templates::amalgamation::get_template::() + ], + locales: { + default: "en-US", + other: ["fr-FR", "es-ES"] + } +} diff --git a/examples/showcase/app/src/pages/about.rs b/examples/showcase/src/templates/about.rs similarity index 82% rename from examples/showcase/app/src/pages/about.rs rename to examples/showcase/src/templates/about.rs index d288ea00e9..ada84d0818 100644 --- a/examples/showcase/app/src/pages/about.rs +++ b/examples/showcase/src/templates/about.rs @@ -1,5 +1,5 @@ use perseus::Template; -use std::sync::Arc; +use std::rc::Rc; use sycamore::prelude::{component, template, GenericNode, Template as SycamoreTemplate}; #[component(AboutPage)] @@ -9,12 +9,12 @@ pub fn about_page() -> SycamoreTemplate { } } -pub fn get_page() -> Template { +pub fn get_template() -> Template { Template::new("about").template(template_fn()) } pub fn template_fn() -> perseus::template::TemplateFn { - Arc::new(|_, _| { + Rc::new(|_, _| { template! { AboutPage() } diff --git a/examples/showcase/app/src/pages/amalgamation.rs b/examples/showcase/src/templates/amalgamation.rs similarity index 88% rename from examples/showcase/app/src/pages/amalgamation.rs rename to examples/showcase/src/templates/amalgamation.rs index 2346307c2e..5adfc855df 100644 --- a/examples/showcase/app/src/pages/amalgamation.rs +++ b/examples/showcase/src/templates/amalgamation.rs @@ -1,6 +1,6 @@ use perseus::{Request, States, StringResultWithCause, Template}; use serde::{Deserialize, Serialize}; -use std::sync::Arc; +use std::rc::Rc; use sycamore::prelude::{component, template, GenericNode, Template as SycamoreTemplate}; #[derive(Serialize, Deserialize, Debug)] @@ -15,11 +15,11 @@ pub fn about_page(props: AmalagamationPageProps) -> SycamoreTemplate { } } -pub fn get_page() -> Template { +pub fn get_template() -> Template { Template::new("amalgamation") - .build_state_fn(Arc::new(get_build_state)) - .request_state_fn(Arc::new(get_request_state)) - .amalgamate_states_fn(Arc::new(amalgamate_states)) + .build_state_fn(Rc::new(get_build_state)) + .request_state_fn(Rc::new(get_request_state)) + .amalgamate_states_fn(Rc::new(amalgamate_states)) .template(template_fn()) } @@ -57,7 +57,7 @@ pub async fn get_request_state(_path: String, _req: Request) -> StringResultWith } pub fn template_fn() -> perseus::template::TemplateFn { - Arc::new(|props, _| { + Rc::new(|props, _| { template! { AboutPage( serde_json::from_str::(&props.unwrap()).unwrap() diff --git a/examples/showcase/app/src/pages/index.rs b/examples/showcase/src/templates/index.rs similarity index 82% rename from examples/showcase/app/src/pages/index.rs rename to examples/showcase/src/templates/index.rs index cc350af35f..fe83bb8ccd 100644 --- a/examples/showcase/app/src/pages/index.rs +++ b/examples/showcase/src/templates/index.rs @@ -1,6 +1,6 @@ use perseus::{StringResultWithCause, Template}; use serde::{Deserialize, Serialize}; -use std::sync::Arc; +use std::rc::Rc; use sycamore::prelude::{component, template, GenericNode, Template as SycamoreTemplate}; #[derive(Serialize, Deserialize, Debug)] @@ -12,13 +12,12 @@ pub struct IndexPageProps { pub fn index_page(props: IndexPageProps) -> SycamoreTemplate { template! { p {(props.greeting)} - a(href = "/about") { "About!" } } } -pub fn get_page() -> Template { +pub fn get_template() -> Template { Template::new("index") - .build_state_fn(Arc::new(get_static_props)) + .build_state_fn(Rc::new(get_static_props)) .template(template_fn()) } @@ -30,7 +29,7 @@ pub async fn get_static_props(_path: String) -> StringResultWithCause { } pub fn template_fn() -> perseus::template::TemplateFn { - Arc::new(|props, _| { + Rc::new(|props, _| { template! { IndexPage( serde_json::from_str::(&props.unwrap()).unwrap() diff --git a/examples/showcase/app/src/pages/ip.rs b/examples/showcase/src/templates/ip.rs similarity index 89% rename from examples/showcase/app/src/pages/ip.rs rename to examples/showcase/src/templates/ip.rs index 64e85ce04d..b8a0fb3e7e 100644 --- a/examples/showcase/app/src/pages/ip.rs +++ b/examples/showcase/src/templates/ip.rs @@ -2,7 +2,7 @@ use perseus::{Request, StringResultWithCause, Template}; use serde::{Deserialize, Serialize}; -use std::sync::Arc; +use std::rc::Rc; use sycamore::prelude::{component, template, GenericNode, Template as SycamoreTemplate}; #[derive(Serialize, Deserialize)] @@ -21,9 +21,9 @@ pub fn dashboard_page(props: IpPageProps) -> SycamoreTemplate { } } -pub fn get_page() -> Template { +pub fn get_template() -> Template { Template::new("ip") - .request_state_fn(Arc::new(get_request_state)) + .request_state_fn(Rc::new(get_request_state)) .template(template_fn()) } @@ -42,7 +42,7 @@ pub async fn get_request_state(_path: String, req: Request) -> StringResultWithC } pub fn template_fn() -> perseus::template::TemplateFn { - Arc::new(|props, _| { + Rc::new(|props, _| { template! { IpPage( serde_json::from_str::(&props.unwrap()).unwrap() diff --git a/examples/showcase/src/templates/mod.rs b/examples/showcase/src/templates/mod.rs new file mode 100644 index 0000000000..31cfb062d8 --- /dev/null +++ b/examples/showcase/src/templates/mod.rs @@ -0,0 +1,8 @@ +pub mod about; +pub mod amalgamation; +pub mod index; +pub mod ip; +pub mod new_post; +pub mod post; +pub mod time; +pub mod time_root; diff --git a/examples/showcase/app/src/pages/new_post.rs b/examples/showcase/src/templates/new_post.rs similarity index 82% rename from examples/showcase/app/src/pages/new_post.rs rename to examples/showcase/src/templates/new_post.rs index 98719e6f78..5720b24b12 100644 --- a/examples/showcase/app/src/pages/new_post.rs +++ b/examples/showcase/src/templates/new_post.rs @@ -1,5 +1,5 @@ use perseus::Template; -use std::sync::Arc; +use std::rc::Rc; use sycamore::prelude::{component, template, GenericNode, Template as SycamoreTemplate}; #[component(NewPostPage)] @@ -9,12 +9,12 @@ pub fn new_post_page() -> SycamoreTemplate { } } -pub fn get_page() -> Template { +pub fn get_template() -> Template { Template::new("post/new").template(template_fn()) } pub fn template_fn() -> perseus::template::TemplateFn { - Arc::new(|_, _| { + Rc::new(|_, _| { template! { NewPostPage() } diff --git a/examples/showcase/app/src/pages/post.rs b/examples/showcase/src/templates/post.rs similarity index 88% rename from examples/showcase/app/src/pages/post.rs rename to examples/showcase/src/templates/post.rs index 1b731f04e6..4a6dae67a6 100644 --- a/examples/showcase/app/src/pages/post.rs +++ b/examples/showcase/src/templates/post.rs @@ -1,6 +1,6 @@ use perseus::{ErrorCause, StringResultWithCause, Template}; use serde::{Deserialize, Serialize}; -use std::sync::Arc; +use std::rc::Rc; use sycamore::prelude::{component, template, GenericNode, Template as SycamoreTemplate}; #[derive(Serialize, Deserialize)] @@ -23,10 +23,10 @@ pub fn post_page(props: PostPageProps) -> SycamoreTemplate { } } -pub fn get_page() -> Template { +pub fn get_template() -> Template { Template::new("post") - .build_paths_fn(Arc::new(get_static_paths)) - .build_state_fn(Arc::new(get_static_props)) + .build_paths_fn(Rc::new(get_static_paths)) + .build_state_fn(Rc::new(get_static_props)) .incremental_path_rendering(true) .template(template_fn()) } @@ -55,7 +55,7 @@ pub async fn get_static_paths() -> Result, String> { } pub fn template_fn() -> perseus::template::TemplateFn { - Arc::new(|props, _| { + Rc::new(|props, _| { template! { PostPage( serde_json::from_str::(&props.unwrap()).unwrap() diff --git a/examples/showcase/app/src/pages/time.rs b/examples/showcase/src/templates/time.rs similarity index 86% rename from examples/showcase/app/src/pages/time.rs rename to examples/showcase/src/templates/time.rs index 283effec00..9c4feea6b2 100644 --- a/examples/showcase/app/src/pages/time.rs +++ b/examples/showcase/src/templates/time.rs @@ -1,6 +1,6 @@ use perseus::{StringResultWithCause, Template}; use serde::{Deserialize, Serialize}; -use std::sync::Arc; +use std::rc::Rc; use sycamore::prelude::{component, template, GenericNode, Template as SycamoreTemplate}; #[derive(Serialize, Deserialize, Debug)] @@ -15,14 +15,14 @@ pub fn time_page(props: TimePageProps) -> SycamoreTemplate { } } -pub fn get_page() -> Template { +pub fn get_template() -> Template { Template::new("timeisr") .template(template_fn()) // This page will revalidate every five seconds (to illustrate revalidation) .revalidate_after("5s".to_string()) .incremental_path_rendering(true) - .build_state_fn(Arc::new(get_build_state)) - .build_paths_fn(Arc::new(get_build_paths)) + .build_state_fn(Rc::new(get_build_state)) + .build_paths_fn(Rc::new(get_build_paths)) } pub async fn get_build_state(_path: String) -> StringResultWithCause { @@ -37,7 +37,7 @@ pub async fn get_build_paths() -> Result, String> { } pub fn template_fn() -> perseus::template::TemplateFn { - Arc::new(|props, _| { + Rc::new(|props, _| { template! { TimePage( serde_json::from_str::(&props.unwrap()).unwrap() diff --git a/examples/showcase/app/src/pages/time_root.rs b/examples/showcase/src/templates/time_root.rs similarity index 85% rename from examples/showcase/app/src/pages/time_root.rs rename to examples/showcase/src/templates/time_root.rs index 53216b9e20..111d879343 100644 --- a/examples/showcase/app/src/pages/time_root.rs +++ b/examples/showcase/src/templates/time_root.rs @@ -1,6 +1,6 @@ use perseus::{StringResultWithCause, Template}; use serde::{Deserialize, Serialize}; -use std::sync::Arc; +use std::rc::Rc; use sycamore::prelude::{component, template, GenericNode, Template as SycamoreTemplate}; #[derive(Serialize, Deserialize, Debug)] @@ -15,14 +15,14 @@ pub fn time_page(props: TimePageProps) -> SycamoreTemplate { } } -pub fn get_page() -> Template { +pub fn get_template() -> Template { Template::new("time") .template(template_fn()) // This page will revalidate every five seconds (to illustrate revalidation) // Try changing this to a week, even though the below custom logic says to always revalidate, we'll only do it weekly .revalidate_after("5s".to_string()) - .should_revalidate_fn(Arc::new(|| async { Ok(true) })) - .build_state_fn(Arc::new(get_build_state)) + .should_revalidate_fn(Rc::new(|| async { Ok(true) })) + .build_state_fn(Rc::new(get_build_state)) } pub async fn get_build_state(_path: String) -> StringResultWithCause { @@ -33,7 +33,7 @@ pub async fn get_build_state(_path: String) -> StringResultWithCause { } pub fn template_fn() -> perseus::template::TemplateFn { - Arc::new(|props, _| { + Rc::new(|props, _| { template! { TimePage( serde_json::from_str::(&props.unwrap()).unwrap() diff --git a/examples/showcase/translations/en-US.ftl b/examples/showcase/translations/en-US.ftl new file mode 100644 index 0000000000..23bece71ed --- /dev/null +++ b/examples/showcase/translations/en-US.ftl @@ -0,0 +1,2 @@ +hello = Hello, { $user }! +about = Welcome to the about page (English)! diff --git a/examples/showcase/translations/es-ES.ftl b/examples/showcase/translations/es-ES.ftl new file mode 100644 index 0000000000..264c978f4a --- /dev/null +++ b/examples/showcase/translations/es-ES.ftl @@ -0,0 +1,2 @@ +hello = Hola! +about = Welcome to the about page (Spanish)! diff --git a/examples/showcase/translations/fr-FR.ftl b/examples/showcase/translations/fr-FR.ftl new file mode 100644 index 0000000000..b4073b1ba4 --- /dev/null +++ b/examples/showcase/translations/fr-FR.ftl @@ -0,0 +1,2 @@ +hello = Bonjour! +about = Welcome to the about page (French)! diff --git a/packages/perseus-actix-web/Cargo.toml b/packages/perseus-actix-web/Cargo.toml index e44828ae61..17b4b9e2db 100644 --- a/packages/perseus-actix-web/Cargo.toml +++ b/packages/perseus-actix-web/Cargo.toml @@ -21,4 +21,4 @@ urlencoding = "2.1" serde_json = "1" error-chain = "0.12" futures = "0.3" -sycamore = { version = "0.5.1", features = ["ssr"] } +sycamore = { version = "0.5", features = ["ssr"] } diff --git a/packages/perseus/Cargo.toml b/packages/perseus/Cargo.toml index 2a298bdc52..872a80568e 100644 --- a/packages/perseus/Cargo.toml +++ b/packages/perseus/Cargo.toml @@ -14,8 +14,8 @@ categories = ["wasm", "web-programming", "development-tools", "asynchronous", "g # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -sycamore = { version = "0.5.1", features = ["ssr"] } -sycamore-router = "0.5.1" +sycamore = { version = "0.5", features = ["ssr"] } +sycamore-router = "0.5" web-sys = { version = "0.3", features = ["Headers", "Request", "RequestInit", "RequestMode", "Response", "ReadableStream", "Window"] } wasm-bindgen = { version = "0.2", features = ["serde-serialize"] } wasm-bindgen-futures = "0.4"