Updated all the examples to use the new leptos_options, and make cargo-leptos porting easy. Refactored the Tailwind example to bring it closer to leptos norms

This commit is contained in:
Ben Wishovich 2022-12-21 23:08:39 -08:00
parent 0d314224c9
commit 428999fd14
24 changed files with 924 additions and 241 deletions

View file

@ -1,5 +1,5 @@
[package]
name = "leptos-counter-isomorphic"
name = "leptos_counter_isomorphic"
version = "0.1.0"
edition = "2021"
@ -42,3 +42,28 @@ ssr = [
[package.metadata.cargo-all-features]
denylist = ["actix-files", "actix-web", "leptos_actix"]
skip_feature_sets = [["csr", "ssr"], ["csr", "hydrate"], ["ssr", "hydrate"]]
[package.metadata.leptos]
# The name used by wasm-bindgen/cargo-leptos for the JS/WASM bundle. Defaults to the crate name
package_name = "leptos_counter_isomorphic"
# The site root folder is where cargo-leptos generate all output. WARNING: all content of this folder will be erased on a rebuild. Use it in your server setup.
site_root = "/pkg"
# The site_root relative folder where all compiled output (JS, WASM and CSS) is written
# Defaults to pkg
site_pkg_dir = "pkg"
# [Optional] The source CSS file. If it ends with .sass or .scss then it will be compiled by dart-sass into CSS. The CSS is optimized by Lightning CSS before being written to <site_root>/<site_pkg>/app.css
# style_file = "src/styles/tailwind.css"
# [Optional] Files in the asset_dir will be copied to the site_root directory
assets_dir = "static/assets"
# The IP and port (ex: 127.0.0.1:3000) where the server serves the content. Use it in your server setup.
site_address = "127.0.0.1:3000"
# The port to use for automatic reload monitoring
reload_port = 3001
# [Optional] Command to use when running end2end tests. It will run in the end2end dir.
end2end_cmd = "npx playwright test"
# The browserlist query used for optimizing the CSS.
browserquery = "defaults"
# Set by cargo-leptos watch when building with tha tool. Controls whether autoreload JS will be included in the head
watch = false
# The environment Leptos will run in, usually either "DEV" or "PROD"
env = "DEV"

View file

@ -9,9 +9,9 @@ use broadcaster::BroadcastChannel;
#[cfg(feature = "ssr")]
pub fn register_server_functions() {
GetServerCount::register();
AdjustServerCount::register();
ClearServerCount::register();
_ = GetServerCount::register();
_ = AdjustServerCount::register();
_ = ClearServerCount::register();
}
#[cfg(feature = "ssr")]

View file

@ -9,7 +9,6 @@ cfg_if! {
use actix_files::{Files};
use actix_web::*;
use crate::counters::*;
use std::{net::SocketAddr, env};
#[get("/api/events")]
async fn counter_events() -> impl Responder {
@ -30,17 +29,17 @@ cfg_if! {
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let addr = SocketAddr::from(([127,0,0,1],3000));
crate::counters::register_server_functions();
let conf = get_configuration().await.unwrap();
let addr = conf.leptos_options.site_address.clone();
HttpServer::new(move || {
let render_options: RenderOptions = RenderOptions::builder().pkg_path("/pkg/leptos_counter_isomorphic").reload_port(3001).socket_address(addr.clone()).environment(&env::var("RUST_ENV")).build();
render_options.write_to_file();
let leptos_options = &conf.leptos_options;
App::new()
.service(Files::new("/pkg", "./pkg"))
.service(counter_events)
.route("/api/{tail:.*}", leptos_actix::handle_server_fns())
.route("/{tail:.*}", leptos_actix::render_app_to_stream(render_options, |cx| view! { cx, <Counters/> }))
.route("/{tail:.*}", leptos_actix::render_app_to_stream(leptos_options.to_owned(), |cx| view! { cx, <Counters/> }))
//.wrap(middleware::Compress::default())
})
.bind(&addr)?

View file

@ -1,5 +1,5 @@
[package]
name = "leptos-hackernews-axum"
name = "leptos_hackernews_axum"
version = "0.1.0"
edition = "2021"
@ -49,3 +49,28 @@ ssr = [
[package.metadata.cargo-all-features]
denylist = ["axum", "tower", "tower-http", "tokio", "http", "leptos_axum"]
skip_feature_sets = [["csr", "ssr"], ["csr", "hydrate"], ["ssr", "hydrate"]]
[package.metadata.leptos]
# The name used by wasm-bindgen/cargo-leptos for the JS/WASM bundle. Defaults to the crate name
package_name = "leptos_hackernews_axum"
# The site root folder is where cargo-leptos generate all output. WARNING: all content of this folder will be erased on a rebuild. Use it in your server setup.
site_root = "/pkg"
# The site_root relative folder where all compiled output (JS, WASM and CSS) is written
# Defaults to pkg
site_pkg_dir = "pkg"
# [Optional] The source CSS file. If it ends with .sass or .scss then it will be compiled by dart-sass into CSS. The CSS is optimized by Lightning CSS before being written to <site_root>/<site_pkg>/app.css
# style_file = "src/styles/tailwind.css"
# [Optional] Files in the asset_dir will be copied to the site_root directory
assets_dir = "static/assets"
# The IP and port (ex: 127.0.0.1:3000) where the server serves the content. Use it in your server setup.
site_address = "127.0.0.1:3000"
# The port to use for automatic reload monitoring
reload_port = 3001
# [Optional] Command to use when running end2end tests. It will run in the end2end dir.
end2end_cmd = "npx playwright test"
# The browserlist query used for optimizing the CSS.
browserquery = "defaults"
# Set by cargo-leptos watch when building with tha tool. Controls whether autoreload JS will be included in the head
watch = false
# The environment Leptos will run in, usually either "DEV" or "PROD"
env = "DEV"

View file

@ -12,7 +12,6 @@ if #[cfg(feature = "ssr")] {
use http::StatusCode;
use std::net::SocketAddr;
use tower_http::services::ServeDir;
use std::env;
#[tokio::main]
async fn main() {
@ -37,14 +36,15 @@ if #[cfg(feature = "ssr")] {
)
}
let render_options: RenderOptions = RenderOptions::builder().pkg_path("/pkg/leptos_hackernews_axum").socket_address(addr).reload_port(3001).environment(&env::var("RUST_ENV")).build();
render_options.write_to_file();
let conf = get_configuration().await.unwrap();
let leptos_options = conf.leptos_options;
let addr = leptos_options.site_address.clone();
// build our application with a route
let app = Router::new()
// `GET /` goes to `root`
.nest_service("/pkg", pkg_service)
.nest_service("/static", static_service)
.fallback(leptos_axum::render_app_to_stream(render_options, |cx| view! { cx, <App/> }));
.fallback(leptos_axum::render_app_to_stream(leptos_options, |cx| view! { cx, <App/> }));
// run our app with hyper
// `axum::Server` is a re-export of `hyper::Server`

View file

@ -14,10 +14,12 @@ console_log = "0.2"
console_error_panic_hook = "0.1"
futures = "0.3"
cfg-if = "1"
leptos = { version = "0.0.20", default-features = false, features = ["serde"] }
leptos_meta = { version = "0.0", default-features = false }
leptos_actix = { version = "0.0.2", default-features = false, optional = true }
leptos_router = { version = "0.0", default-features = false }
leptos = { path = "../../leptos", default-features = false, features = [
"serde",
] }
leptos_actix = { path = "../../integrations/actix", optional = true }
leptos_meta = { path = "../../meta", default-features = false }
leptos_router = { path = "../../router", default-features = false }
log = "0.4"
simple_logger = "2"
serde = { version = "1", features = ["derive"] }
@ -43,3 +45,28 @@ ssr = [
[package.metadata.cargo-all-features]
denylist = ["actix-files", "actix-web", "leptos_actix"]
skip_feature_sets = [["csr", "ssr"], ["csr", "hydrate"], ["ssr", "hydrate"]]
[package.metadata.leptos]
# The name used by wasm-bindgen/cargo-leptos for the JS/WASM bundle. Defaults to the crate name
package_name = "leptos-hackernews"
# The site root folder is where cargo-leptos generate all output. WARNING: all content of this folder will be erased on a rebuild. Use it in your server setup.
site_root = "target/site"
# The site_root relative folder where all compiled output (JS, WASM and CSS) is written
# Defaults to pkg
site_pkg_dir = "pkg"
# [Optional] The source CSS file. If it ends with .sass or .scss then it will be compiled by dart-sass into CSS. The CSS is optimized by Lightning CSS before being written to <site_root>/<site_pkg>/app.css
# style_file = "src/styles/tailwind.css"
# [Optional] Files in the asset_dir will be copied to the site_root directory
# assets_dir = "static/assets"
# The IP and port (ex: 127.0.0.1:3000) where the server serves the content. Use it in your server setup.
site_address = "127.0.0.1:3000"
# The port to use for automatic reload monitoring
reload_port = 3001
# [Optional] Command to use when running end2end tests. It will run in the end2end dir.
end2end_cmd = "npx playwright test"
# The browserlist query used for optimizing the CSS.
browserquery = "defaults"
# Set by cargo-leptos watch when building with tha tool. Controls whether autoreload JS will be included in the head
watch = false
# The environment Leptos will run in, usually either "DEV" or "PROD"
env = "DEV"

View file

@ -8,7 +8,6 @@ cfg_if! {
use actix_files::{Files};
use actix_web::*;
use leptos_hackernews::*;
use std::{net::SocketAddr, env};
#[get("/style.css")]
async fn css() -> impl Responder {
@ -17,16 +16,15 @@ cfg_if! {
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let addr = SocketAddr::from(([127,0,0,1],3000));
let conf = get_configuration().await.unwrap();
let addr = conf.leptos_options.site_address.clone();
HttpServer::new(move || {
let render_options: RenderOptions = RenderOptions::builder().pkg_path("/pkg/leptos_hackernews").reload_port(3001).socket_address(addr.clone()).environment(&env::var("RUST_ENV")).build();
render_options.write_to_file();
let leptos_options = &conf.leptos_options;
App::new()
.service(Files::new("/pkg", "./pkg"))
.service(css)
.route("/api/{tail:.*}", leptos_actix::handle_server_fns())
.route("/{tail:.*}", leptos_actix::render_app_to_stream(render_options, |cx| view! { cx, <App/> }))
.route("/{tail:.*}", leptos_actix::render_app_to_stream(leptos_options.to_owned(), |cx| view! { cx, <App/> }))
//.wrap(middleware::Compress::default())
})
.bind(&addr)?

View file

@ -1,7 +1,7 @@
[workspace]
[package]
name = "example"
name = "leptos_tailwind_example"
version = "0.1.0"
edition = "2021"
@ -12,12 +12,12 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
leptos = { git = "https://github.com/gbj/leptos", default-features = false, features = [
"serde",
leptos = { path = "../../leptos", default-features = false, features = [
"serde",
] }
leptos_meta = { git = "https://github.com/gbj/leptos", default-features = false }
leptos_router = { git = "https://github.com/gbj/leptos", default-features = false }
leptos_actix = { path = "../../integrations/actix", optional = true }
leptos_meta = { path = "../../meta", default-features = false }
leptos_router = { path = "../../router", default-features = false }
gloo-net = { version = "0.2", features = ["http"] }
log = "0.4"
cfg-if = "1.0"
@ -35,13 +35,9 @@ simple_logger = { version = "4.0", optional = true }
serde_json = { version = "1.0", optional = true }
reqwest = { version = "0.11", features = ["json"], optional = true }
[profile.release]
codegen-units = 1
lto = true
opt-level = 'z'
[features]
leptos_autoreload = []
default = ["csr"]
hydrate = [
"leptos/hydrate",
@ -64,6 +60,7 @@ ssr = [
"leptos_meta/ssr",
"leptos_router/ssr",
"dep:reqwest",
"dep:leptos_actix",
"dep:actix-web",
"dep:actix-files",
"dep:futures",
@ -71,22 +68,36 @@ ssr = [
"dep:serde_json",
]
[package.metadata.leptos]
# Path, relative to root, to generat rust code to
gen_file = "src/server/generated.rs"
# Path to the source index.html file
index_file = "index.html"
# [Optional] Files in the asset_dir will be copied to the target/site directory
assets_dir = "assets"
# [Optional] Command to use when running end2end tests. It will run in the end2end dir.
end2end_test_cmd = "npx playwright test"
# On which port to serve the client side rendered site (when using --csr option)
csr_port = 3000
# The port to use for automatic reload monitoring
reload_port = 3001
[package.metadata.cargo-all-features]
denylist = ["actix-files", "actix-web", "leptos_actix"]
skip_feature_sets = [["csr", "ssr"], ["csr", "hydrate"], ["ssr", "hydrate"]]
[package.metadata.leptos.style]
# This points to the TailwindCSS output file
file = "style/output.css"
# A https://browsersl.ist query
browserquery = "defaults"
# [profile.release]
# codegen-units = 1
# lto = true
# opt-level = 'z'
[package.metadata.leptos]
# The name used by wasm-bindgen/cargo-leptos for the JS/WASM bundle. Defaults to the crate name
package_name = "leptos_tailwind_example"
# The site root folder is where cargo-leptos generate all output. WARNING: all content of this folder will be erased on a rebuild. Use it in your server setup.
site_root = "/pkg"
# The site_root relative folder where all compiled output (JS, WASM and CSS) is written
# Defaults to pkg
site_pkg_dir = "pkg"
# [Optional] The source CSS file. If it ends with .sass or .scss then it will be compiled by dart-sass into CSS. The CSS is optimized by Lightning CSS before being written to <site_root>/<site_pkg>/app.css
# style_file = "src/styles/tailwind.css"
# [Optional] Files in the asset_dir will be copied to the site_root directory
assets_dir = "assets"
# The IP and port (ex: 127.0.0.1:3000) where the server serves the content. Use it in your server setup.
site_address = "127.0.0.1:3000"
# The port to use for automatic reload monitoring
reload_port = 3001
# [Optional] Command to use when running end2end tests. It will run in the end2end dir.
end2end_cmd = "npx playwright test"
# The browserlist query used for optimizing the CSS.
browserquery = "defaults"
# Set by cargo-leptos watch when building with tha tool. Controls whether autoreload JS will be included in the head
watch = false
# The environment Leptos will run in, usually either "DEV" or "PROD"
env = "DEV"

View file

@ -16,7 +16,7 @@ and
in this directory.
You can begin editing your app at `src/app/mod.rs`.
You can begin editing your app at `src/app.rs`.
## Installing Tailwind
@ -69,6 +69,37 @@ By default, `cargo-leptos` uses `nightly` Rust, `cargo-generate`, and `sass`. If
4. `cargo install cargo-generate` - install `cargo-generate` binary (should be installed automatically in future)
5. `npm install -g sass` - install `dart-sass` (should be optional in future
## Alternatives to cargo-leptos
This crate can be run without `cargo-leptos`, using `wasm-pack` and `cargo`. To do so, you'll need to install some other tools.
1. `cargo install wasm-pack`
### Server Side Rendering With Hydration
To run it as a server side app with hydration, first you should run
```bash
wasm-pack build --target=web --no-default-features --features=hydrate
```
to generate the WebAssembly to hydrate the HTML delivered from the server.
Then run the server with `cargo run` to serve the server side rendered HTML and the WASM bundle for hydration.
```bash
cargo run --no-default-features --features=ssr
```
> Note that if your hydration code changes, you will have to rerun the wasm-pack command above before running
> `cargo run`
### Client Side Rendering
You'll need to install trunk to client side render this bundle.
1. `cargo install trunk`
Then the site can be served with `trunk serve --open`
## Attribution
Many thanks to GreatGreg for putting together this guide. You can find the original, with added details, [here](https://github.com/gbj/leptos/discussions/125).

View file

@ -9,6 +9,7 @@ pub fn App(cx: Scope) -> Element {
view! {
cx,
<main class="my-0 mx-auto max-w-3xl text-center">
<Stylesheet id="leptos" href="/style.css"/>
<h2 class="p-6 text-4xl">"Welcome to Leptos with Tailwind"</h2>
<p class="px-10 pb-10 text-left">"Tailwind will scan your Rust files for Tailwind class names and compile them into a CSS file."</p>
<button

View file

@ -4,22 +4,23 @@ use cfg_if::cfg_if;
cfg_if! {
if #[cfg(feature = "hydrate")] {
use wasm_bindgen::prelude::wasm_bindgen;
#[wasm_bindgen(start)]
pub fn main() {
use app::*;
use leptos::*;
use wasm_bindgen::prelude::wasm_bindgen;
use crate::app::*;
use leptos::*;
_ = console_log::init_with_level(log::Level::Debug);
console_error_panic_hook::set_once();
#[wasm_bindgen]
pub fn hydrate() {
console_error_panic_hook::set_once();
_ = console_log::init_with_level(log::Level::Debug);
console_error_panic_hook::set_once();
log!("hydrate mode - hydrating");
log!("hydrate mode - hydrating");
leptos::hydrate(body().unwrap(), move |cx| {
view! { cx, <App/> }
});
}
leptos::hydrate(body().unwrap(), |cx| {
view! { cx, <App/> }
});
}
}
else if #[cfg(feature = "csr")] {

View file

@ -1,14 +1,34 @@
mod app;
#[cfg(feature = "ssr")]
mod server;
use cfg_if::cfg_if;
cfg_if! {
if #[cfg(feature = "ssr")] {
use actix_files::Files;
use actix_web::*;
use leptos::*;
use crate::app::*;
#[get("/style.css")]
async fn css() -> impl Responder {
actix_files::NamedFile::open_async("./style/output.css").await
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
server::run().await
let conf = get_configuration().await.unwrap();
let addr = conf.leptos_options.site_address.clone();
HttpServer::new(move || {
let leptos_options = &conf.leptos_options;
App::new()
.service(css)
.service(Files::new("/pkg", "./pkg"))
.route("/{tail:.*}", leptos_actix::render_app_to_stream(leptos_options.to_owned(), |cx| view! { cx, <App/> }))
.wrap(middleware::Compress::default())
})
.bind(&addr)?
.run()
.await
}
}
else {

View file

@ -1,49 +0,0 @@
//! THIS FILE IS AUTOGENERATED, DO NOT MODIFY
//! When building, `cargo-leptos` generates this file based on
//! the `index.html` file specified in the Config.toml
//!
//! This file can be commited to version control. It only
//! changes when the configuration changes
#[cfg(feature = "leptos_autoreload")]
/// index.html content up to `<!-- INJECT HEAD -->` plus `cargo leptos` injected css and js content.
pub const HTML_START: &str = r##"<!DOCTYPE html>
<html lang="en">
<head>
<title>Cargo Leptos</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script type="module">import init from '/pkg/app.js';init('/pkg/app.wasm');</script>
<link rel="preload" href="/pkg/app.wasm" as="fetch" type="application/wasm" crossorigin="">
<link rel="stylesheet" href="/pkg/app.css">
<link rel="modulepreload" href="/pkg/app.js">
<script crossorigin="">(function () {
var ws = new WebSocket('ws://127.0.0.1:3001/autoreload');
ws.onmessage = (ev) => {
console.log(`Reload message: `);
if (ev.data === 'reload') window.location.reload();
};
ws.onclose = () => console.warn('Autoreload stopped. Manual reload necessary.');
})()
</script>"##;
#[cfg(not(feature = "leptos_autoreload"))]
/// index.html content up to `<!-- INJECT HEAD -->` plus `cargo leptos` injected css and js content.
pub const HTML_START: &str = r##"<!DOCTYPE html>
<html lang="en">
<head>
<title>Cargo Leptos</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script type="module">import init from '/pkg/app.js';init('/pkg/app.wasm');</script>
<link rel="preload" href="/pkg/app.wasm" as="fetch" type="application/wasm" crossorigin="">
<link rel="stylesheet" href="/pkg/app.css">
<link rel="modulepreload" href="/pkg/app.js">"##;
/// index.html content from `<!-- INJECT HEAD -->` up to `<!-- INJECT BODY -->`
pub const HTML_MIDDLE: &str = r##" </head>
<body>"##;
/// index.html content from `<!-- INJECT BODY -->` until the end
pub const HTML_END: &str = r##" </body>
</html>"##;

View file

@ -1,92 +0,0 @@
mod generated;
use crate::app::*;
use actix_files::Files;
use actix_web::*;
use futures::StreamExt;
use generated::{HTML_END, HTML_MIDDLE, HTML_START};
use leptos::*;
use leptos_meta::*;
use leptos_router::*;
#[derive(Copy, Clone, Debug)]
struct ActixIntegration {
path: ReadSignal<String>,
}
impl History for ActixIntegration {
fn location(&self, cx: leptos::Scope) -> ReadSignal<LocationChange> {
create_signal(
cx,
LocationChange {
value: self.path.get(),
replace: false,
scroll: true,
state: State(None),
},
)
.0
}
fn navigate(&self, _loc: &LocationChange) {}
}
// match every path — our router will handle actual dispatch
#[get("{tail:.*}")]
async fn render_app(req: HttpRequest) -> impl Responder {
let path = req.path();
let query = req.query_string();
let path = if query.is_empty() {
"http://leptos".to_string() + path
} else {
"http://leptos".to_string() + path + "?" + query
};
let app = move |cx| {
let integration = ActixIntegration {
path: create_signal(cx, path.clone()).0,
};
provide_context(cx, RouterIntegrationContext(std::rc::Rc::new(integration)));
view! { cx, <App /> }
};
HttpResponse::Ok().content_type("text/html").streaming(
futures::stream::once(async { HTML_START.to_string() })
.chain(render_to_stream(move |cx| {
use_context::<MetaContext>(cx)
.map(|meta| meta.dehydrate())
.unwrap_or_default()
}))
.chain(futures::stream::once(async { HTML_MIDDLE.to_string() }))
.chain(render_to_stream(move |cx| app(cx).to_string()))
.chain(futures::stream::once(async { HTML_END.to_string() }))
.map(|html| Ok(web::Bytes::from(html)) as Result<web::Bytes>),
)
}
pub async fn run() -> std::io::Result<()> {
let host = std::env::var("HOST").unwrap_or_else(|_| "127.0.0.1".to_string());
let port = std::env::var("PORT")
.unwrap_or_else(|_| "3000".to_string())
.parse::<u16>()
.unwrap();
simple_logger::init_with_level(log::Level::Debug).expect("couldn't initialize logging");
log::info!("serving at {host}:{port}");
HttpServer::new(|| {
App::new()
.service(
web::scope("/pkg")
.service(Files::new("", "target/site/pkg"))
.wrap(middleware::Compress::default()),
)
.service(render_app)
})
.bind((host, port))?
.run()
.await
}

View file

@ -0,0 +1,621 @@
/*
! tailwindcss v3.1.8 | MIT License | https://tailwindcss.com
*/
/*
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
*/
*,
::before,
::after {
box-sizing: border-box;
/* 1 */
border-width: 0;
/* 2 */
border-style: solid;
/* 2 */
border-color: #e5e7eb;
/* 2 */
}
::before,
::after {
--tw-content: '';
}
/*
1. Use a consistent sensible line-height in all browsers.
2. Prevent adjustments of font size after orientation changes in iOS.
3. Use a more readable tab size.
4. Use the user's configured `sans` font-family by default.
*/
html {
line-height: 1.5;
/* 1 */
-webkit-text-size-adjust: 100%;
/* 2 */
-moz-tab-size: 4;
/* 3 */
-o-tab-size: 4;
tab-size: 4;
/* 3 */
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
/* 4 */
}
/*
1. Remove the margin in all browsers.
2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
*/
body {
margin: 0;
/* 1 */
line-height: inherit;
/* 2 */
}
/*
1. Add the correct height in Firefox.
2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
3. Ensure horizontal rules are visible by default.
*/
hr {
height: 0;
/* 1 */
color: inherit;
/* 2 */
border-top-width: 1px;
/* 3 */
}
/*
Add the correct text decoration in Chrome, Edge, and Safari.
*/
abbr:where([title]) {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
}
/*
Remove the default font size and weight for headings.
*/
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: inherit;
font-weight: inherit;
}
/*
Reset links to optimize for opt-in styling instead of opt-out.
*/
a {
color: inherit;
text-decoration: inherit;
}
/*
Add the correct font weight in Edge and Safari.
*/
b,
strong {
font-weight: bolder;
}
/*
1. Use the user's configured `mono` font family by default.
2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp,
pre {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
/* 1 */
font-size: 1em;
/* 2 */
}
/*
Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/*
Prevent `sub` and `sup` elements from affecting the line height in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/*
1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
3. Remove gaps between table borders by default.
*/
table {
text-indent: 0;
/* 1 */
border-color: inherit;
/* 2 */
border-collapse: collapse;
/* 3 */
}
/*
1. Change the font styles in all browsers.
2. Remove the margin in Firefox and Safari.
3. Remove default padding in all browsers.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit;
/* 1 */
font-size: 100%;
/* 1 */
font-weight: inherit;
/* 1 */
line-height: inherit;
/* 1 */
color: inherit;
/* 1 */
margin: 0;
/* 2 */
padding: 0;
/* 3 */
}
/*
Remove the inheritance of text transform in Edge and Firefox.
*/
button,
select {
text-transform: none;
}
/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Remove default button styles.
*/
button,
[type='button'],
[type='reset'],
[type='submit'] {
-webkit-appearance: button;
/* 1 */
background-color: transparent;
/* 2 */
background-image: none;
/* 2 */
}
/*
Use the modern Firefox focus style for all focusable elements.
*/
:-moz-focusring {
outline: auto;
}
/*
Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
*/
:-moz-ui-invalid {
box-shadow: none;
}
/*
Add the correct vertical alignment in Chrome and Firefox.
*/
progress {
vertical-align: baseline;
}
/*
Correct the cursor style of increment and decrement buttons in Safari.
*/
::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
height: auto;
}
/*
1. Correct the odd appearance in Chrome and Safari.
2. Correct the outline style in Safari.
*/
[type='search'] {
-webkit-appearance: textfield;
/* 1 */
outline-offset: -2px;
/* 2 */
}
/*
Remove the inner padding in Chrome and Safari on macOS.
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button;
/* 1 */
font: inherit;
/* 2 */
}
/*
Add the correct display in Chrome and Safari.
*/
summary {
display: list-item;
}
/*
Removes the default spacing and border for appropriate elements.
*/
blockquote,
dl,
dd,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
figure,
p,
pre {
margin: 0;
}
fieldset {
margin: 0;
padding: 0;
}
legend {
padding: 0;
}
ol,
ul,
menu {
list-style: none;
margin: 0;
padding: 0;
}
/*
Prevent resizing textareas horizontally by default.
*/
textarea {
resize: vertical;
}
/*
1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
2. Set the default placeholder color to the user's configured gray 400 color.
*/
input::-moz-placeholder, textarea::-moz-placeholder {
opacity: 1;
/* 1 */
color: #9ca3af;
/* 2 */
}
input::placeholder,
textarea::placeholder {
opacity: 1;
/* 1 */
color: #9ca3af;
/* 2 */
}
/*
Set the default cursor for buttons.
*/
button,
[role="button"] {
cursor: pointer;
}
/*
Make sure disabled buttons don't get the pointer cursor.
*/
:disabled {
cursor: default;
}
/*
1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
This can trigger a poorly considered lint error in some tools but is included by design.
*/
img,
svg,
video,
canvas,
audio,
iframe,
embed,
object {
display: block;
/* 1 */
vertical-align: middle;
/* 2 */
}
/*
Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
*/
img,
video {
max-width: 100%;
height: auto;
}
*, ::before, ::after {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
::-webkit-backdrop {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
::backdrop {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
.my-0 {
margin-top: 0px;
margin-bottom: 0px;
}
.mx-auto {
margin-left: auto;
margin-right: auto;
}
.max-w-3xl {
max-width: 48rem;
}
.rounded-lg {
border-radius: 0.5rem;
}
.bg-sky-600 {
--tw-bg-opacity: 1;
background-color: rgb(2 132 199 / var(--tw-bg-opacity));
}
.p-6 {
padding: 1.5rem;
}
.px-10 {
padding-left: 2.5rem;
padding-right: 2.5rem;
}
.px-5 {
padding-left: 1.25rem;
padding-right: 1.25rem;
}
.py-3 {
padding-top: 0.75rem;
padding-bottom: 0.75rem;
}
.pb-10 {
padding-bottom: 2.5rem;
}
.text-left {
text-align: left;
}
.text-center {
text-align: center;
}
.text-4xl {
font-size: 2.25rem;
line-height: 2.5rem;
}
.text-white {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity));
}
.hover\:bg-sky-700:hover {
--tw-bg-opacity: 1;
background-color: rgb(3 105 161 / var(--tw-bg-opacity));
}

View file

@ -1,5 +1,5 @@
[package]
name = "todo-app-cbor"
name = "todo_app_cbor"
version = "0.1.0"
edition = "2021"
@ -46,3 +46,28 @@ ssr = [
[package.metadata.cargo-all-features]
denylist = ["actix-files", "actix-web", "leptos_actix", "sqlx"]
skip_feature_sets = [["csr", "ssr"], ["csr", "hydrate"], ["ssr", "hydrate"]]
[package.metadata.leptos]
# The name used by wasm-bindgen/cargo-leptos for the JS/WASM bundle. Defaults to the crate name
package_name = "todo_app_cbor"
# The site root folder is where cargo-leptos generate all output. WARNING: all content of this folder will be erased on a rebuild. Use it in your server setup.
site_root = "/pkg"
# The site_root relative folder where all compiled output (JS, WASM and CSS) is written
# Defaults to pkg
site_pkg_dir = "pkg"
# [Optional] The source CSS file. If it ends with .sass or .scss then it will be compiled by dart-sass into CSS. The CSS is optimized by Lightning CSS before being written to <site_root>/<site_pkg>/app.css
# style_file = "src/styles/tailwind.css"
# [Optional] Files in the asset_dir will be copied to the site_root directory
# assets_dir = "static/assets"
# The IP and port (ex: 127.0.0.1:3000) where the server serves the content. Use it in your server setup.
site_address = "127.0.0.1:3000"
# The port to use for automatic reload monitoring
reload_port = 3001
# [Optional] Command to use when running end2end tests. It will run in the end2end dir.
end2end_cmd = "npx playwright test"
# The browserlist query used for optimizing the CSS.
browserquery = "defaults"
# Set by cargo-leptos watch when building with tha tool. Controls whether autoreload JS will be included in the head
watch = false
# The environment Leptos will run in, usually either "DEV" or "PROD"
env = "DEV"

View file

@ -9,7 +9,6 @@ cfg_if! {
use actix_files::{Files};
use actix_web::*;
use crate::todo::*;
use std::{ net::SocketAddr,env };
#[get("/style.css")]
async fn css() -> impl Responder {
@ -25,16 +24,15 @@ cfg_if! {
.expect("could not run SQLx migrations");
crate::todo::register_server_functions();
let addr = SocketAddr::from(([127,0,0,1],3000));
let conf = get_configuration().await.unwrap();
let addr = conf.leptos_options.site_address.clone();
HttpServer::new(move || {
let render_options: RenderOptions = RenderOptions::builder().pkg_path("/pkg/todo_app_sqlite").reload_port(3001).socket_address(addr.clone()).environment(&env::var("RUST_ENV")).build();
render_options.write_to_file();
let leptos_options = &conf.leptos_options;
App::new()
.service(Files::new("/pkg", "./pkg"))
.service(css)
.route("/api/{tail:.*}", leptos_actix::handle_server_fns())
.route("/{tail:.*}", leptos_actix::render_app_to_stream(render_options, |cx| view! { cx, <TodoApp/> }))
.route("/{tail:.*}", leptos_actix::render_app_to_stream(leptos_options.to_owned(), |cx| view! { cx, <TodoApp/> }))
//.wrap(middleware::Compress::default())
})
.bind(&addr)?

View file

@ -1,5 +1,5 @@
[package]
name = "todo-app-sqlite-axum"
name = "todo_app_sqlite_axum"
version = "0.1.0"
edition = "2021"
@ -60,3 +60,28 @@ denylist = [
"leptos_axum",
]
skip_feature_sets = [["csr", "ssr"], ["csr", "hydrate"], ["ssr", "hydrate"]]
[package.metadata.leptos]
# The name used by wasm-bindgen/cargo-leptos for the JS/WASM bundle. Defaults to the crate name
package_name = "todo_app_sqlite_axum"
# The site root folder is where cargo-leptos generate all output. WARNING: all content of this folder will be erased on a rebuild. Use it in your server setup.
site_root = "/pkg"
# The site_root relative folder where all compiled output (JS, WASM and CSS) is written
# Defaults to pkg
site_pkg_dir = "pkg"
# [Optional] The source CSS file. If it ends with .sass or .scss then it will be compiled by dart-sass into CSS. The CSS is optimized by Lightning CSS before being written to <site_root>/<site_pkg>/app.css
# style_file = "src/styles/tailwind.css"
# [Optional] Files in the asset_dir will be copied to the site_root directory
# assets_dir = "static/assets"
# The IP and port (ex: 127.0.0.1:3000) where the server serves the content. Use it in your server setup.
site_address = "127.0.0.1:3000"
# The port to use for automatic reload monitoring
reload_port = 3001
# [Optional] Command to use when running end2end tests. It will run in the end2end dir.
end2end_cmd = "npx playwright test"
# The browserlist query used for optimizing the CSS.
browserquery = "defaults"
# Set by cargo-leptos watch when building with tha tool. Controls whether autoreload JS will be included in the head
watch = false
# The environment Leptos will run in, usually either "DEV" or "PROD"
env = "DEV"

View file

@ -9,18 +9,13 @@ if #[cfg(feature = "ssr")] {
error_handling::HandleError,
Router,
};
use std::net::SocketAddr;
use crate::todo::*;
use todo_app_sqlite_axum::*;
use http::StatusCode;
use tower_http::services::ServeDir;
use std::env;
#[tokio::main]
async fn main() {
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
log::debug!("serving at {addr}");
simple_logger::init_with_level(log::Level::Debug).expect("couldn't initialize logging");
let mut conn = db().await.expect("couldn't connect to DB");
@ -46,19 +41,22 @@ if #[cfg(feature = "ssr")] {
}
let render_options: RenderOptions = RenderOptions::builder().pkg_path("/pkg/todo_app_sqlite_axum").socket_address(addr).reload_port(3001).environment(&env::var("RUST_ENV")).build();
render_options.write_to_file();
let conf = get_configuration().await.unwrap();
let leptos_options = conf.leptos_options;
let addr = leptos_options.site_address.clone();
log::debug!("serving at {addr}");
// build our application with a route
let app = Router::new()
.route("/api/*fn_name", post(leptos_axum::handle_server_fns))
.nest_service("/pkg", pkg_service)
.nest_service("/static", static_service)
.fallback(leptos_axum::render_app_to_stream(render_options.clone(), |cx| view! { cx, <TodoApp/> }));
.fallback(leptos_axum::render_app_to_stream(leptos_options, |cx| view! { cx, <TodoApp/> }));
// run our app with hyper
// `axum::Server` is a re-export of `hyper::Server`
log!("listening on {}", &render_options.socket_address);
axum::Server::bind(&render_options.socket_address)
log!("listening on {}", &addr);
axum::Server::bind(&addr)
.serve(app.into_make_service())
.await
.unwrap();

View file

@ -1,5 +1,5 @@
[package]
name = "todo-app-sqlite"
name = "todo_app_sqlite"
version = "0.1.0"
edition = "2021"
@ -39,3 +39,28 @@ ssr = ["dep:actix-files", "dep:actix-web", "dep:sqlx", "leptos/ssr", "leptos_act
[package.metadata.cargo-all-features]
denylist = ["actix-files", "actix-web", "leptos_actix", "sqlx"]
skip_feature_sets = [["csr", "ssr"], ["csr", "hydrate"], ["ssr", "hydrate"]]
[package.metadata.leptos]
# The name used by wasm-bindgen/cargo-leptos for the JS/WASM bundle. Defaults to the crate name
package_name = "todo_app_sqlite"
# The site root folder is where cargo-leptos generate all output. WARNING: all content of this folder will be erased on a rebuild. Use it in your server setup.
site_root = "/pkg"
# The site_root relative folder where all compiled output (JS, WASM and CSS) is written
# Defaults to pkg
site_pkg_dir = "pkg"
# [Optional] The source CSS file. If it ends with .sass or .scss then it will be compiled by dart-sass into CSS. The CSS is optimized by Lightning CSS before being written to <site_root>/<site_pkg>/app.css
# style_file = "src/styles/tailwind.css"
# [Optional] Files in the asset_dir will be copied to the site_root directory
# assets_dir = "static/assets"
# The IP and port (ex: 127.0.0.1:3000) where the server serves the content. Use it in your server setup.
site_address = "127.0.0.1:3000"
# The port to use for automatic reload monitoring
reload_port = 3001
# [Optional] Command to use when running end2end tests. It will run in the end2end dir.
end2end_cmd = "npx playwright test"
# The browserlist query used for optimizing the CSS.
browserquery = "defaults"
# Set by cargo-leptos watch when building with tha tool. Controls whether autoreload JS will be included in the head
watch = false
# The environment Leptos will run in, usually either "DEV" or "PROD"
env = "DEV"

View file

@ -1,5 +1,3 @@
use std::net::SocketAddr;
use cfg_if::cfg_if;
use leptos::*;
mod todo;
@ -11,7 +9,7 @@ cfg_if! {
use actix_files::{Files};
use actix_web::*;
use crate::todo::*;
use std::env;
#[get("/style.css")]
async fn css() -> impl Responder {
@ -28,16 +26,15 @@ cfg_if! {
crate::todo::register_server_functions();
let addr = SocketAddr::from(([127,0,0,1],3000));
let conf = get_configuration().await.unwrap();
let addr = conf.leptos_options.site_address.clone();
HttpServer::new(move || {
let render_options: RenderOptions = RenderOptions::builder().pkg_path("/pkg/todo_app_sqlite").reload_port(3001).socket_address(addr.clone()).environment(&env::var("RUST_ENV")).build();
render_options.write_to_file();
let leptos_options = &conf.leptos_options;
App::new()
.service(Files::new("/pkg", "./pkg"))
.service(css)
.route("/api/{tail:.*}", leptos_actix::handle_server_fns())
.route("/{tail:.*}", leptos_actix::render_app_to_stream(render_options, |cx| view! { cx, <TodoApp/> }))
.route("/{tail:.*}", leptos_actix::render_app_to_stream(leptos_options.to_owned(), |cx| view! { cx, <TodoApp/> }))
//.wrap(middleware::Compress::default())
})
.bind(&addr)?

View file

@ -7,8 +7,6 @@ use serde::{Deserialize, Serialize};
cfg_if! {
if #[cfg(feature = "ssr")] {
use sqlx::{Connection, SqliteConnection};
use http::{header::SET_COOKIE, HeaderMap, HeaderValue, StatusCode};
pub async fn db() -> Result<SqliteConnection, ServerFnError> {
Ok(SqliteConnection::connect("sqlite:Todos.db").await.map_err(|e| ServerFnError::ServerError(e.to_string()))?)

View file

@ -1,5 +1,5 @@
use actix_web::{http::header::HeaderMap, web::Bytes, *};
use futures::{StreamExt, executor};
use futures::{StreamExt};
use http::StatusCode;
use leptos::*;

View file

@ -122,7 +122,6 @@ impl MetaContext {
tags.push_str(&title);
tags.push_str("</title>");
}
println!("Stylesheets {:#?}", &self.stylesheets);
// Stylesheets
tags.push_str(&self.stylesheets.as_string());