Skip to content
This repository has been archived by the owner on Jul 19, 2020. It is now read-only.

Relax capture rules in Fragment sections in route syntax parser #211

Merged
merged 3 commits into from
Dec 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions crates/yew_router_route_parser/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,14 +184,6 @@ pub fn capture<'a>(
map(capture_impl(field_naming_scheme), RouteParserToken::Capture)
}

pub fn capture_single<'a>(
field_naming_scheme: FieldNamingScheme,
) -> impl Fn(&'a str) -> IResult<&'a str, RouteParserToken<'a>, ParseError> {
map(
capture_single_impl(field_naming_scheme),
RouteParserToken::Capture,
)
}

fn capture_single_impl<'a>(
field_naming_scheme: FieldNamingScheme,
Expand Down
22 changes: 16 additions & 6 deletions crates/yew_router_route_parser/src/optimizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,18 @@ pub fn parse_str_and_optimize_tokens(
/// In the process of converting the tokens, this function will condense multiple RouteParserTokens
/// that represent literals into one Exact variant if multiple reducible tokens happen to occur in a row.
pub fn convert_tokens(tokens: &[RouteParserToken]) -> Vec<MatcherToken> {
let mut new_tokens = vec![];
let mut new_tokens: Vec<MatcherToken> = vec![];
let mut run: Vec<RouteParserToken> = vec![];

fn empty_run(run: &mut Vec<RouteParserToken>) -> MatcherToken {
fn empty_run(run: &mut Vec<RouteParserToken>) -> Option<MatcherToken> {
let segment = run.iter().map(RouteParserToken::as_str).collect::<String>();
run.clear();

MatcherToken::Exact(segment)
if !segment.is_empty() {
Some(MatcherToken::Exact(segment))
} else {
None
}
}

fn empty_run_with_query_cap_at_end(
Expand All @@ -95,7 +99,9 @@ pub fn convert_tokens(tokens: &[RouteParserToken]) -> Vec<MatcherToken> {
| RouteParserToken::QuerySeparator
| RouteParserToken::Exact(_) => run.push(*token),
RouteParserToken::Capture(cap) => {
new_tokens.push(empty_run(&mut run));
if let Some(current_run) = empty_run(&mut run) {
new_tokens.push(current_run);
}
new_tokens.push(MatcherToken::Capture(CaptureVariant::from(*cap)))
}
RouteParserToken::Query {
Expand All @@ -113,7 +119,9 @@ pub fn convert_tokens(tokens: &[RouteParserToken]) -> Vec<MatcherToken> {
}
},
RouteParserToken::End => {
new_tokens.push(empty_run(&mut run));
if let Some(current_run) = empty_run(&mut run) {
new_tokens.push(current_run);
}
new_tokens.push(MatcherToken::End);
}
RouteParserToken::Nothing => {}
Expand All @@ -122,7 +130,9 @@ pub fn convert_tokens(tokens: &[RouteParserToken]) -> Vec<MatcherToken> {

// Empty the run at the end.
if !run.is_empty() {
new_tokens.push(empty_run(&mut run));
if let Some(current_run) = empty_run(&mut run) {
new_tokens.push(current_run);
}
}

new_tokens
Expand Down
8 changes: 4 additions & 4 deletions crates/yew_router_route_parser/src/parser.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! Parser that consumes a string and produces the first representation of the matcher.
use crate::{
core::{
capture, capture_single, exact, fragment_exact, get_and, get_end, get_hash, get_question,
get_slash, nothing, query,
capture, exact, fragment_exact, get_and, get_end, get_hash, get_question, get_slash,
nothing, query,
},
error::{get_reason, ParseError, ParserErrorReason, PrettyParseError},
FieldNamingScheme,
Expand Down Expand Up @@ -388,9 +388,9 @@ fn parse_impl<'a>(
},
ParserState::Fragment { prev_token } => match prev_token {
RouteParserToken::FragmentBegin => {
alt((fragment_exact, capture_single(field_naming_scheme), get_end))(i)
alt((fragment_exact, capture(field_naming_scheme), get_end))(i)
}
RouteParserToken::Exact(_) => alt((capture_single(field_naming_scheme), get_end))(i),
RouteParserToken::Exact(_) => alt((capture(field_naming_scheme), get_end))(i),
RouteParserToken::Capture(_) => alt((fragment_exact, get_end))(i),
_ => Err(nom::Err::Failure(ParseError {
reason: Some(ParserErrorReason::InvalidState),
Expand Down
2 changes: 1 addition & 1 deletion examples/minimal/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ impl Component for Model {
AppRoute::C => format!("/c"),
};
self.route_service.set_route(&route_string, ());
self.route = Route{
self.route = Route {
route: route_string,
state: (),
};
Expand Down
44 changes: 21 additions & 23 deletions examples/router_component/src/a_component.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use crate::{c_component::CModel, ARoute};
use crate::{c_component::CModel, ARoute, AppRoute};
use yew::{prelude::*, virtual_dom::VNode, Properties};
use yew_router::prelude::*;
use yew_router::switch::AllowMissing;
use crate::AppRoute;
use yew_router::{prelude::*, switch::AllowMissing};

pub struct AModel {
props: Props,
Expand Down Expand Up @@ -35,25 +33,25 @@ impl Component for AModel {

fn view(&self) -> VNode {
html! {
<div>
{ "I am the A component"}
<div>
<RouterButton<AppRoute> route=AppRoute::A(AllowMissing(Some(ARoute)))>
{"Go to a/c"}
</RouterButton>
// <RouterButton route="/a/d">
// {"Go to a/d (route does not exist)"}
// </RouterButton>
</div>
<div>
{
match self.props.route {
Some(_) => html!{<CModel/>},
None => html!{}
}
<div>
{ "I am the A component"}
<div>
<RouterButton<AppRoute> route=AppRoute::A(AllowMissing(Some(ARoute)))>
{"Go to a/c"}
</RouterButton>
// <RouterButton route="/a/d">
// {"Go to a/d (route does not exist)"}
// </RouterButton>
</div>
<div>
{
match self.props.route {
Some(_) => html!{<CModel/>},
None => html!{}
}
}
</div>
</div>
}
</div>
</div>
}
}
}
1 change: 0 additions & 1 deletion examples/router_component/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,3 @@ pub enum AppRoute {
#[derive(Debug, Switch, PartialEq, Clone, Copy)]
#[to = "/c"]
pub struct ARoute;

3 changes: 1 addition & 2 deletions examples/switch/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use yew_router::{route::Route, Switch};
use yew_router::switch::Permissive;
use yew_router::{route::Route, switch::Permissive, Switch};

fn main() {
let route = Route::new_no_state("/some/route");
Expand Down
2 changes: 1 addition & 1 deletion src/agent/bridge.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Bridge to RouteAgent.
use crate::{agent::{RouteAgent}, route::Route, RouteState};
use crate::{agent::RouteAgent, route::Route, RouteState};
use std::{
fmt::{Debug, Error as FmtError, Formatter},
ops::{Deref, DerefMut},
Expand Down
7 changes: 3 additions & 4 deletions src/agent/dispatcher.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
//! Dispatcher to RouteAgent.
use crate::agent::{RouteAgent};
use crate::{agent::RouteAgent, RouteState};
use std::{
fmt::{Debug, Error as FmtError, Formatter},
ops::{Deref, DerefMut},
};
use yew::agent::{Dispatched, Dispatcher};
use crate::RouteState;

/// A wrapped dispatcher to the route agent.
///
Expand All @@ -16,7 +15,7 @@ where

impl<STATE> RouteAgentDispatcher<STATE>
where
STATE: RouteState
STATE: RouteState,
{
/// Creates a new bridge.
pub fn new() -> Self {
Expand All @@ -27,7 +26,7 @@ where

impl<STATE> Default for RouteAgentDispatcher<STATE>
where
STATE: RouteState
STATE: RouteState,
{
fn default() -> Self {
Self::new()
Expand Down
13 changes: 4 additions & 9 deletions src/agent/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ mod dispatcher;
pub use dispatcher::RouteAgentDispatcher;



/// Internal Message used for the RouteAgent.
#[derive(Debug)]
pub enum Msg<STATE> {
Expand Down Expand Up @@ -122,23 +121,20 @@ where
match msg {
RouteRequest::ReplaceRoute(route) => {
let route_string: String = route.to_string();
self.route_service
.replace_route(&route_string, route.state);
self.route_service.replace_route(&route_string, route.state);
let route = self.route_service.get_route();
for sub in &self.subscribers {
self.link.respond(*sub, route.clone());
}
}
RouteRequest::ReplaceRouteNoBroadcast(route) => {
let route_string: String = route.to_string();
self.route_service
.replace_route(&route_string, route.state);
self.route_service.replace_route(&route_string, route.state);
}
RouteRequest::ChangeRoute(route) => {
let route_string: String = route.to_string();
// set the route
self.route_service
.set_route(&route_string, route.state);
self.route_service.set_route(&route_string, route.state);
// get the new route.
let route = self.route_service.get_route();
// broadcast it to all listening components
Expand All @@ -148,8 +144,7 @@ where
}
RouteRequest::ChangeRouteNoBroadcast(route) => {
let route_string: String = route.to_string();
self.route_service
.set_route(&route_string, route.state);
self.route_service.set_route(&route_string, route.state);
}
RouteRequest::GetCurrentRoute => {
let route = self.route_service.get_route();
Expand Down
7 changes: 5 additions & 2 deletions src/components/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ use yew::{Children, Properties};

#[allow(deprecated)]
pub use self::{router_button::RouterButton, router_link::RouterAnchor, router_link::RouterLink};
use crate::{Switch};
use crate::Switch;

// TODO This should also be PartialEq and Clone. Its blocked on Children not supporting that.
// TODO This should no longer take link & String, and instead take a route: SW implementing Switch
/// Properties for `RouterButton` and `RouterLink`.
#[derive(Properties, Default, Debug)]
pub struct Props<SW> where SW: Switch {
pub struct Props<SW>
where
SW: Switch,
{
/// The Switched item representing the route.
#[props(required)]
pub route: SW,
Expand Down
8 changes: 6 additions & 2 deletions src/components/router_button.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
//! A component wrapping a `<button>` tag that changes the route.
use crate::{agent::{RouteAgentDispatcher, RouteRequest}, route::Route, Switch};
use crate::{
agent::{RouteAgentDispatcher, RouteRequest},
route::Route,
Switch,
};
use yew::prelude::*;

use super::{Msg, Props};
Expand All @@ -14,7 +18,7 @@ pub struct RouterButton<SW: Switch + Clone + 'static, STATE: RouterState = ()> {
props: Props<SW>,
}

impl<SW: Switch + Clone + 'static, STATE: RouterState> Component for RouterButton<SW, STATE> {
impl<SW: Switch + Clone + 'static, STATE: RouterState> Component for RouterButton<SW, STATE> {
type Message = Msg;
type Properties = Props<SW>;

Expand Down
38 changes: 21 additions & 17 deletions src/components/router_link.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
//! A component wrapping an `<a>` tag that changes the route.
use crate::{agent::{RouteAgentDispatcher, RouteRequest}, route::Route, Switch};
use crate::{
agent::{RouteAgentDispatcher, RouteRequest},
route::Route,
Switch,
};
use yew::prelude::*;

use super::{Msg, Props};
Expand Down Expand Up @@ -50,25 +54,25 @@ impl<SW: Switch + Clone + 'static, STATE: RouterState> Component for RouterAncho

fn view(&self) -> VNode {
use stdweb::web::event::IEvent;
// let target: &str = &self.props.link;
// let target: &str = &self.props.link;
let cb = |x| self.link.callback(x);

html! {
<a
class=self.props.classes.clone(),
onclick=cb(|event: ClickEvent | {
event.prevent_default();
Msg::Clicked
}),
disabled=self.props.disabled,
// href=target,
>
{
#[allow(deprecated)]
&self.props.text
<a
class=self.props.classes.clone(),
onclick=cb(|event: ClickEvent | {
event.prevent_default();
Msg::Clicked
}),
disabled=self.props.disabled,
// href=target,
>
{
#[allow(deprecated)]
&self.props.text
}
{self.props.children.iter().collect::<VNode>()}
</a>
}
{self.props.children.iter().collect::<VNode>()}
</a>
}
}
}
10 changes: 6 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ pub mod unit_state {
pub mod prelude {
pub use super::matcher::Captures;

#[cfg(feature = "service")]
pub use crate::service::RouteService;
#[cfg(feature = "service")]
pub use crate::route::RouteState;
#[cfg(feature = "service")]
pub use crate::service::RouteService;

#[cfg(feature = "agent")]
pub use crate::agent::RouteAgent;
Expand All @@ -109,8 +109,10 @@ pub mod prelude {
#[cfg(feature = "router")]
pub use crate::router::RouterState;

pub use crate::route::Route;
pub use crate::switch::{Switch, Routable};
pub use crate::{
route::Route,
switch::{Routable, Switch},
};
pub use yew_router_macro::Switch;
}

Expand Down
2 changes: 1 addition & 1 deletion src/matcher/matcher_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ fn matcher_impl<'a, 'b: 'a, CAP: CaptureCollection<'b>>(
settings: MatcherSettings,
mut i: &'a str,
) -> IResult<&'a str, CAP> {
trace!("Attempting to match path: {:?} using: {:?}", i, tokens);
trace!("Attempting to match route: {:?} using: {:?}", i, tokens);

let mut iter = tokens.iter().peekable();

Expand Down
Loading