Fix cargo test --workspace, associated feature flags, and a number of doctests
This commit is contained in:
1 parent
fdd77d79c1
commit
8df53df887
11 files changed
+218
-187
No files matched your search
@@ -117,12 +117,14 @@ impl DesktopService {
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// # async fn app() {
|
||||
/// // Create a new window with a component that will be rendered in the new window.
|
||||
/// let dom = VirtualDom::new(popup);
|
||||
/// // Create and wait for the window
|
||||
/// let window = dioxus::desktop::window().new_window(dom, Default::default()).await;
|
||||
/// // Fullscreen the new window
|
||||
/// window.set_fullscreen(true);
|
||||
/// # }
|
||||
/// ```
|
||||
// Note: This method is asynchronous because webview2 does not support creating a new window from
|
||||
// inside of an existing webview callback. Dioxus runs event handlers synchronously inside of a webview
|
||||
@@ -323,12 +325,21 @@ fn is_main_thread() -> bool {
|
||||
/// A [`DesktopContext`] that is pending creation.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// ```rust, no_run
|
||||
/// # use dioxus::prelude::*;
|
||||
/// # async fn app() {
|
||||
/// // Create a new window with a component that will be rendered in the new window.
|
||||
/// let dom = VirtualDom::new(|| rsx!{ "popup!" });
|
||||
///
|
||||
/// // Create a new window asynchronously
|
||||
/// let pending_context = desktop_service.new_window(dom, config);
|
||||
/// let pending_context = dioxus::desktop::window().new_window(dom, Default::default());
|
||||
///
|
||||
/// // Wait for the context to be created
|
||||
/// let window = pending_context.await;
|
||||
///
|
||||
/// // Now control the window
|
||||
/// window.set_fullscreen(true);
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct PendingDesktopContext {
|
||||
pub(crate) receiver: tokio::sync::oneshot::Receiver<DesktopContext>,
|
||||
|
||||
@@ -135,6 +135,15 @@ impl ServerFnError {
|
||||
/// # Examples
|
||||
/// ```rust
|
||||
/// use dioxus::prelude::*;
|
||||
/// use serde::{Serialize, Deserialize};
|
||||
///
|
||||
/// #[derive(Serialize, Deserialize, Debug)]
|
||||
/// struct MyCustomError;
|
||||
/// impl std::fmt::Display for MyCustomError {
|
||||
/// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
/// write!(f, "My custom error")
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// #[server]
|
||||
/// async fn server_function() -> ServerFnResult<String, MyCustomError> {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::AssetOptions;
|
||||
use const_serialize::SerializeConst;
|
||||
use std::collections::HashSet;
|
||||
|
||||
/// Options for a css asset
|
||||
#[derive(
|
||||
@@ -76,177 +75,3 @@ impl CssAssetOptions {
|
||||
AssetOptions::Css(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Options for a css module asset
|
||||
#[derive(
|
||||
Debug,
|
||||
Eq,
|
||||
PartialEq,
|
||||
PartialOrd,
|
||||
Clone,
|
||||
Copy,
|
||||
Hash,
|
||||
SerializeConst,
|
||||
serde::Serialize,
|
||||
serde::Deserialize,
|
||||
)]
|
||||
#[non_exhaustive]
|
||||
pub struct CssModuleAssetOptions {
|
||||
minify: bool,
|
||||
preload: bool,
|
||||
}
|
||||
|
||||
impl Default for CssModuleAssetOptions {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl CssModuleAssetOptions {
|
||||
/// Create a new css asset using the builder
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
preload: false,
|
||||
minify: true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets whether the css should be minified (default: true)
|
||||
///
|
||||
/// Minifying the css can make your site load faster by loading less data
|
||||
///
|
||||
/// ```rust
|
||||
/// # use manganis::{styles, CssModuleAssetOptions};
|
||||
/// styles!(STYLES, "/assets/style.css", CssModuleAssetOptions::new().with_minify(false));
|
||||
/// ```
|
||||
#[allow(unused)]
|
||||
pub const fn with_minify(self, minify: bool) -> Self {
|
||||
Self { minify, ..self }
|
||||
}
|
||||
|
||||
/// Check if the asset is minified
|
||||
pub const fn minified(&self) -> bool {
|
||||
self.minify
|
||||
}
|
||||
|
||||
/// Make the asset preloaded
|
||||
///
|
||||
/// Preloading css will make the image start to load as soon as possible. This is useful for css that is used soon after the page loads or css that may not be used immediately, but should start loading sooner
|
||||
///
|
||||
/// ```rust
|
||||
/// # use manganis::{asset, Asset, CssAssetOptions};
|
||||
/// styles!("/assets/style.css", CssAssetOptions::new().with_preload(true));
|
||||
/// ```
|
||||
#[allow(unused)]
|
||||
pub const fn with_preload(self, preload: bool) -> Self {
|
||||
Self { preload, ..self }
|
||||
}
|
||||
|
||||
/// Check if the asset is preloaded
|
||||
pub const fn preloaded(&self) -> bool {
|
||||
self.preload
|
||||
}
|
||||
|
||||
/// Convert the options into options for a generic asset
|
||||
pub const fn into_asset_options(self) -> AssetOptions {
|
||||
AssetOptions::CssModule(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Collect CSS classes & ids.
|
||||
///
|
||||
/// This is a rudementary css classes & ids collector.
|
||||
/// Idents used only in media queries will not be collected. (not support yet)
|
||||
///
|
||||
/// There are likely a number of edge cases that will show up.
|
||||
///
|
||||
/// Returns `(HashSet<Classes>, HashSet<Ids>)`
|
||||
pub fn collect_css_idents(css: &str) -> (HashSet<String>, HashSet<String>) {
|
||||
const ALLOWED: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-";
|
||||
|
||||
let mut classes = HashSet::new();
|
||||
let mut ids = HashSet::new();
|
||||
|
||||
// Collected ident name and true for ids.
|
||||
let mut start: Option<(String, bool)> = None;
|
||||
|
||||
// True if we have the first comment start delimiter `/`
|
||||
let mut comment_start = false;
|
||||
// True if we have the first comment end delimiter '*'
|
||||
let mut comment_end = false;
|
||||
// True if we're in a comment scope.
|
||||
let mut in_comment_scope = false;
|
||||
|
||||
// True if we're in a block scope: `#hi { this is block scope }`
|
||||
let mut in_block_scope = false;
|
||||
|
||||
// If we are currently collecting an ident:
|
||||
// - Check if the char is allowed, put it into the ident string.
|
||||
// - If not allowed, finalize the ident string and reset start.
|
||||
// Otherwise:
|
||||
// Check if character is a `.` or `#` representing a class or string, and start collecting.
|
||||
for (_byte_index, c) in css.char_indices() {
|
||||
if let Some(ident) = start.as_mut() {
|
||||
if ALLOWED.find(c).is_some() {
|
||||
// CSS ignore idents that start with a number.
|
||||
// 1. Difficult to process
|
||||
// 2. Avoid false positives (transition: 0.5s)
|
||||
if ident.0.is_empty() && c.is_numeric() {
|
||||
start = None;
|
||||
continue;
|
||||
}
|
||||
|
||||
ident.0.push(c);
|
||||
} else {
|
||||
match ident.1 {
|
||||
true => ids.insert(ident.0.clone()),
|
||||
false => classes.insert(ident.0.clone()),
|
||||
};
|
||||
|
||||
start = None;
|
||||
}
|
||||
} else {
|
||||
// Handle entering an exiting scopede.
|
||||
match c {
|
||||
// Mark as comment scope if we have comment start: /*
|
||||
'*' if comment_start => {
|
||||
comment_start = false;
|
||||
in_comment_scope = true;
|
||||
}
|
||||
// Mark start of comment end if in comment scope: */
|
||||
'*' if in_comment_scope => comment_end = true,
|
||||
// Mark as comment start if not in comment scope and no comment start, mark comment_start
|
||||
'/' if !in_comment_scope => {
|
||||
comment_start = true;
|
||||
}
|
||||
// If we get the closing delimiter, mark as non-comment scope.
|
||||
'/' if comment_end => {
|
||||
in_comment_scope = false;
|
||||
comment_start = false;
|
||||
comment_end = false;
|
||||
}
|
||||
// Entering & Exiting block scope.
|
||||
'{' => in_block_scope = true,
|
||||
'}' => in_block_scope = false,
|
||||
// Any other character, reset comment start and end if not in scope.
|
||||
_ => {
|
||||
comment_start = false;
|
||||
comment_end = false;
|
||||
}
|
||||
}
|
||||
|
||||
// No need to process this char if in bad scope.
|
||||
if in_comment_scope || in_block_scope {
|
||||
continue;
|
||||
}
|
||||
|
||||
match c {
|
||||
'.' => start = Some((String::new(), false)),
|
||||
'#' => start = Some((String::new(), true)),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(classes, ids)
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
use crate::AssetOptions;
|
||||
use const_serialize::SerializeConst;
|
||||
use std::collections::HashSet;
|
||||
|
||||
/// Options for a css module asset
|
||||
#[derive(
|
||||
Debug,
|
||||
Eq,
|
||||
PartialEq,
|
||||
PartialOrd,
|
||||
Clone,
|
||||
Copy,
|
||||
Hash,
|
||||
SerializeConst,
|
||||
serde::Serialize,
|
||||
serde::Deserialize,
|
||||
)]
|
||||
#[non_exhaustive]
|
||||
#[doc(hidden)]
|
||||
pub struct CssModuleAssetOptions {
|
||||
minify: bool,
|
||||
preload: bool,
|
||||
}
|
||||
|
||||
impl Default for CssModuleAssetOptions {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl CssModuleAssetOptions {
|
||||
/// Create a new css asset using the builder
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
preload: false,
|
||||
minify: true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets whether the css should be minified (default: true)
|
||||
///
|
||||
/// Minifying the css can make your site load faster by loading less data
|
||||
#[allow(unused)]
|
||||
pub const fn with_minify(self, minify: bool) -> Self {
|
||||
Self { minify, ..self }
|
||||
}
|
||||
|
||||
/// Check if the asset is minified
|
||||
pub const fn minified(&self) -> bool {
|
||||
self.minify
|
||||
}
|
||||
|
||||
/// Make the asset preloaded
|
||||
///
|
||||
/// Preloading css will make the image start to load as soon as possible. This is useful for css that is used soon after the page loads or css that may not be used immediately, but should start loading sooner
|
||||
#[allow(unused)]
|
||||
pub const fn with_preload(self, preload: bool) -> Self {
|
||||
Self { preload, ..self }
|
||||
}
|
||||
|
||||
/// Check if the asset is preloaded
|
||||
pub const fn preloaded(&self) -> bool {
|
||||
self.preload
|
||||
}
|
||||
|
||||
/// Convert the options into options for a generic asset
|
||||
pub const fn into_asset_options(self) -> AssetOptions {
|
||||
AssetOptions::CssModule(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Collect CSS classes & ids.
|
||||
///
|
||||
/// This is a rudementary css classes & ids collector.
|
||||
/// Idents used only in media queries will not be collected. (not support yet)
|
||||
///
|
||||
/// There are likely a number of edge cases that will show up.
|
||||
///
|
||||
/// Returns `(HashSet<Classes>, HashSet<Ids>)`
|
||||
pub fn collect_css_idents(css: &str) -> (HashSet<String>, HashSet<String>) {
|
||||
const ALLOWED: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-";
|
||||
|
||||
let mut classes = HashSet::new();
|
||||
let mut ids = HashSet::new();
|
||||
|
||||
// Collected ident name and true for ids.
|
||||
let mut start: Option<(String, bool)> = None;
|
||||
|
||||
// True if we have the first comment start delimiter `/`
|
||||
let mut comment_start = false;
|
||||
// True if we have the first comment end delimiter '*'
|
||||
let mut comment_end = false;
|
||||
// True if we're in a comment scope.
|
||||
let mut in_comment_scope = false;
|
||||
|
||||
// True if we're in a block scope: `#hi { this is block scope }`
|
||||
let mut in_block_scope = false;
|
||||
|
||||
// If we are currently collecting an ident:
|
||||
// - Check if the char is allowed, put it into the ident string.
|
||||
// - If not allowed, finalize the ident string and reset start.
|
||||
// Otherwise:
|
||||
// Check if character is a `.` or `#` representing a class or string, and start collecting.
|
||||
for (_byte_index, c) in css.char_indices() {
|
||||
if let Some(ident) = start.as_mut() {
|
||||
if ALLOWED.find(c).is_some() {
|
||||
// CSS ignore idents that start with a number.
|
||||
// 1. Difficult to process
|
||||
// 2. Avoid false positives (transition: 0.5s)
|
||||
if ident.0.is_empty() && c.is_numeric() {
|
||||
start = None;
|
||||
continue;
|
||||
}
|
||||
|
||||
ident.0.push(c);
|
||||
} else {
|
||||
match ident.1 {
|
||||
true => ids.insert(ident.0.clone()),
|
||||
false => classes.insert(ident.0.clone()),
|
||||
};
|
||||
|
||||
start = None;
|
||||
}
|
||||
} else {
|
||||
// Handle entering an exiting scopede.
|
||||
match c {
|
||||
// Mark as comment scope if we have comment start: /*
|
||||
'*' if comment_start => {
|
||||
comment_start = false;
|
||||
in_comment_scope = true;
|
||||
}
|
||||
// Mark start of comment end if in comment scope: */
|
||||
'*' if in_comment_scope => comment_end = true,
|
||||
// Mark as comment start if not in comment scope and no comment start, mark comment_start
|
||||
'/' if !in_comment_scope => {
|
||||
comment_start = true;
|
||||
}
|
||||
// If we get the closing delimiter, mark as non-comment scope.
|
||||
'/' if comment_end => {
|
||||
in_comment_scope = false;
|
||||
comment_start = false;
|
||||
comment_end = false;
|
||||
}
|
||||
// Entering & Exiting block scope.
|
||||
'{' => in_block_scope = true,
|
||||
'}' => in_block_scope = false,
|
||||
// Any other character, reset comment start and end if not in scope.
|
||||
_ => {
|
||||
comment_start = false;
|
||||
comment_end = false;
|
||||
}
|
||||
}
|
||||
|
||||
// No need to process this char if in bad scope.
|
||||
if in_comment_scope || in_block_scope {
|
||||
continue;
|
||||
}
|
||||
|
||||
match c {
|
||||
'.' => start = Some((String::new(), false)),
|
||||
'#' => start = Some((String::new(), true)),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(classes, ids)
|
||||
}
|
||||
@@ -15,3 +15,6 @@ pub use js::*;
|
||||
|
||||
mod asset;
|
||||
pub use asset::*;
|
||||
|
||||
mod css_module;
|
||||
pub use css_module::*;
|
||||
@@ -123,7 +123,7 @@ impl ToTokens for CssModuleParser {
|
||||
#[allow(missing_docs, non_snake_case)]
|
||||
mod #mod_name {
|
||||
#[allow(unused_imports)]
|
||||
use super::manganis::{self, CssModuleAssetOptions};
|
||||
use manganis::{self, CssModuleAssetOptions};
|
||||
|
||||
#linker_tokens;
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ pub fn asset(input: TokenStream) -> TokenStream {
|
||||
/// }
|
||||
///
|
||||
/// .button {
|
||||
/// background-color: #373737;
|
||||
/// background-color: #373737;
|
||||
/// }
|
||||
/// ```
|
||||
/// Then you can use the `css_module!()` macro in your Rust project:
|
||||
@@ -163,9 +163,9 @@ pub fn asset(input: TokenStream) -> TokenStream {
|
||||
/// println!("{}", Styles::button);
|
||||
/// ```
|
||||
#[proc_macro]
|
||||
#[doc(hidden)]
|
||||
pub fn css_module(input: TokenStream) -> TokenStream {
|
||||
let style = parse_macro_input!(input as CssModuleParser);
|
||||
|
||||
quote! { #style }.into_token_stream().into()
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
|
||||
#[doc(hidden)]
|
||||
pub mod macro_helpers;
|
||||
pub use manganis_macro::{asset, css_module};
|
||||
pub use manganis_macro::asset;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use manganis_macro::css_module;
|
||||
|
||||
pub use manganis_core::{
|
||||
Asset, AssetOptions, BundledAsset, CssAssetOptions, CssModuleAssetOptions, FolderAssetOptions,
|
||||
|
||||
@@ -92,6 +92,7 @@ full = [
|
||||
"dep:tower-layer",
|
||||
"dep:tokio-util",
|
||||
"dep:hyper-util",
|
||||
"axum/default",
|
||||
]
|
||||
core = [
|
||||
"server_fn/axum-no-default",
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
//! }
|
||||
//!
|
||||
//! fn app() -> Element {
|
||||
//!
|
||||
//! let mut text = use_signal(|| "Click the button to run a server function".to_string());
|
||||
//!
|
||||
//! rsx! {
|
||||
//! button {
|
||||
|
||||
@@ -26,7 +26,9 @@ pub trait DioxusRouterExt<S>: DioxusRouterFnExt<S> {
|
||||
/// ```rust, no_run
|
||||
/// # #![allow(non_snake_case)]
|
||||
/// # use dioxus_lib::prelude::*;
|
||||
/// # use dioxus_fullstack::prelude::*;
|
||||
/// # use dioxus_server::prelude::*;
|
||||
/// use dioxus_server::{DioxusRouterExt, DioxusRouterFnExt};
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() {
|
||||
/// let addr = dioxus::cli_config::fullstack_address_or_localhost();
|
||||
@@ -51,7 +53,9 @@ pub trait DioxusRouterExt<S>: DioxusRouterFnExt<S> {
|
||||
/// ```rust, no_run
|
||||
/// # #![allow(non_snake_case)]
|
||||
/// # use dioxus_lib::prelude::*;
|
||||
/// # use dioxus_fullstack::prelude::*;
|
||||
/// # use dioxus_server::prelude::*;
|
||||
/// use dioxus_server::{DioxusRouterExt, DioxusRouterFnExt};
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() {
|
||||
/// let addr = dioxus::cli_config::fullstack_address_or_localhost();
|
||||
@@ -110,7 +114,7 @@ pub trait DioxusRouterFnExt<S> {
|
||||
/// # Example
|
||||
/// ```rust, no_run
|
||||
/// # use dioxus_lib::prelude::*;
|
||||
/// # use dioxus_fullstack::prelude::*;
|
||||
/// # use dioxus_server::prelude::*;
|
||||
/// #[tokio::main]
|
||||
/// async fn main() {
|
||||
/// let addr = dioxus::cli_config::fullstack_address_or_localhost();
|
||||
@@ -135,7 +139,7 @@ pub trait DioxusRouterFnExt<S> {
|
||||
/// # Example
|
||||
/// ```rust, no_run
|
||||
/// # use dioxus_lib::prelude::*;
|
||||
/// # use dioxus_fullstack::prelude::*;
|
||||
/// # use dioxus_server::prelude::*;
|
||||
/// # use std::sync::Arc;
|
||||
/// #[tokio::main]
|
||||
/// async fn main() {
|
||||
@@ -159,7 +163,8 @@ pub trait DioxusRouterFnExt<S> {
|
||||
/// # Example
|
||||
/// ```rust, no_run
|
||||
/// # use dioxus_lib::prelude::*;
|
||||
/// # use dioxus_fullstack::prelude::*;
|
||||
/// # use dioxus_server::prelude::*;
|
||||
/// # use dioxus_server::prelude::*;
|
||||
/// #[tokio::main]
|
||||
/// async fn main() {
|
||||
/// let router = axum::Router::new()
|
||||
@@ -167,6 +172,11 @@ pub trait DioxusRouterFnExt<S> {
|
||||
/// .into_make_service();
|
||||
/// // ...
|
||||
/// }
|
||||
///
|
||||
/// fn app() -> Element {
|
||||
/// rsx! { "Hello World" }
|
||||
/// }
|
||||
/// ```
|
||||
fn serve_api_application(self, cfg: ServeConfig, app: fn() -> Element) -> Self
|
||||
where
|
||||
Self: Sized;
|
||||
@@ -357,6 +367,7 @@ impl RenderHandleState {
|
||||
///
|
||||
/// use axum::routing::get;
|
||||
/// use dioxus::prelude::*;
|
||||
/// use dioxus_server::{RenderHandleState, render_handler, ServeConfig};
|
||||
///
|
||||
/// fn app() -> Element {
|
||||
/// rsx! {
|
||||
|
||||
Reference in new issue
Block a user