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

Commit

Permalink
Relax capture rules in Fragment sections in route syntax parser (#211)
Browse files Browse the repository at this point in the history
* Relax capture rules in Fragment sections in route syntax parser

* remove dead code for single_capture- only parser

* cargo fmt
  • Loading branch information
hgzimmerman authored Dec 19, 2019
1 parent 1aaa54c commit c1d5242
Show file tree
Hide file tree
Showing 20 changed files with 164 additions and 121 deletions.
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

0 comments on commit c1d5242

Please sign in to comment.