* Add `#[component]` attribute + system for creating component attributes + other stuff * Delete inlineprops.rs * Update inline_props.rs * Cargo fmt * Fix clippy warnings and paths in props/mods.rs * Include where clause in `#[inline_props]` output * Allow Clippy type complexity in `LinkProps` * Allow the type complexity lint for the entire link.rs file * Remove snake_case -> PascalCase converter, but rather enforce PascalCase Also: - Put the second function inside the main one instead of besides it. - Simplify * Simplify type check lints so they don't return false positives They will not always work, but they won't return any false positives, like for aliases. This is likely going to be replaced by a more polished Clippy-backed linting system. * Fix #583 * Cargo fmt * Add docs for `deserialize()` and remove useless comment * Add `#[component]` to prelude * Merge branch 'master' of https://github.com/tigerros/dioxus * #[inline_props] is no more. Except in the docs folder, but that's going to be removed * Remove docs folder * Remove docs from workspace * Resolve `DeserializerOutput` conversation
126 lines
3.7 KiB
Rust
126 lines
3.7 KiB
Rust
//! Types pertaining to navigation.
|
|
|
|
use std::{
|
|
fmt::{Debug, Display},
|
|
str::FromStr,
|
|
};
|
|
|
|
use url::{ParseError, Url};
|
|
|
|
use crate::routable::Routable;
|
|
|
|
/// A target for the router to navigate to.
|
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
|
pub enum NavigationTarget<R> {
|
|
/// An internal path that the router can navigate to by itself.
|
|
///
|
|
/// ```rust
|
|
/// # use dioxus::prelude::*;
|
|
/// # use dioxus_router::prelude::*;
|
|
/// # use dioxus_router::navigation::NavigationTarget;
|
|
/// # #[component]
|
|
/// # fn Index(cx: Scope) -> Element {
|
|
/// # todo!()
|
|
/// # }
|
|
/// #[derive(Clone, Routable, PartialEq, Debug)]
|
|
/// enum Route {
|
|
/// #[route("/")]
|
|
/// Index {},
|
|
/// }
|
|
/// let explicit = NavigationTarget::Internal(Route::Index {});
|
|
/// let implicit: NavigationTarget::<Route> = "/".parse().unwrap();
|
|
/// assert_eq!(explicit, implicit);
|
|
/// ```
|
|
Internal(R),
|
|
/// An external target that the router doesn't control.
|
|
///
|
|
/// ```rust
|
|
/// # use dioxus::prelude::*;
|
|
/// # use dioxus_router::prelude::*;
|
|
/// # use dioxus_router::navigation::NavigationTarget;
|
|
/// # #[component]
|
|
/// # fn Index(cx: Scope) -> Element {
|
|
/// # todo!()
|
|
/// # }
|
|
/// #[derive(Clone, Routable, PartialEq, Debug)]
|
|
/// enum Route {
|
|
/// #[route("/")]
|
|
/// Index {},
|
|
/// }
|
|
/// let explicit = NavigationTarget::<Route>::External(String::from("https://dioxuslabs.com/"));
|
|
/// let implicit: NavigationTarget::<Route> = "https://dioxuslabs.com/".parse().unwrap();
|
|
/// assert_eq!(explicit, implicit);
|
|
/// ```
|
|
External(String),
|
|
}
|
|
|
|
impl<R: Routable> From<&str> for NavigationTarget<R> {
|
|
fn from(value: &str) -> Self {
|
|
value
|
|
.parse()
|
|
.unwrap_or_else(|_| Self::External(value.to_string()))
|
|
}
|
|
}
|
|
|
|
impl<R: Routable> From<&String> for NavigationTarget<R> {
|
|
fn from(value: &String) -> Self {
|
|
value.as_str().into()
|
|
}
|
|
}
|
|
|
|
impl<R: Routable> From<String> for NavigationTarget<R> {
|
|
fn from(value: String) -> Self {
|
|
value.as_str().into()
|
|
}
|
|
}
|
|
|
|
impl<R: Routable> From<R> for NavigationTarget<R> {
|
|
fn from(value: R) -> Self {
|
|
Self::Internal(value)
|
|
}
|
|
}
|
|
|
|
impl<R: Routable> Display for NavigationTarget<R> {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
NavigationTarget::Internal(r) => write!(f, "{}", r),
|
|
NavigationTarget::External(s) => write!(f, "{}", s),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// An error that can occur when parsing a [`NavigationTarget`].
|
|
pub enum NavigationTargetParseError<R: Routable> {
|
|
/// A URL that is not valid.
|
|
InvalidUrl(ParseError),
|
|
/// An internal URL that is not valid.
|
|
InvalidInternalURL(<R as FromStr>::Err),
|
|
}
|
|
|
|
impl<R: Routable> Debug for NavigationTargetParseError<R> {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
NavigationTargetParseError::InvalidUrl(e) => write!(f, "Invalid URL: {}", e),
|
|
NavigationTargetParseError::InvalidInternalURL(_) => {
|
|
write!(f, "Invalid internal URL")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<R: Routable> FromStr for NavigationTarget<R> {
|
|
type Err = NavigationTargetParseError<R>;
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
match Url::parse(s) {
|
|
Ok(_) => Ok(Self::External(s.to_string())),
|
|
Err(ParseError::RelativeUrlWithoutBase) => {
|
|
Ok(Self::Internal(R::from_str(s).map_err(|e| {
|
|
NavigationTargetParseError::InvalidInternalURL(e)
|
|
})?))
|
|
}
|
|
Err(e) => Err(NavigationTargetParseError::InvalidUrl(e)),
|
|
}
|
|
}
|
|
}
|