From 0f529c5625f4670d66244ce990f71fcf1228bb61 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sun, 3 Feb 2019 11:44:44 -0500 Subject: [PATCH] 3.0.4 --- CHANGELOG.md | 5 +++ lib/src/grammar.dart | 79 ++++++++++++++++++------------------- lib/src/route.dart | 28 ++++++++++--- lib/src/router.dart | 5 ++- lib/src/routing_result.dart | 4 +- pubspec.yaml | 2 +- test/wildcard_test.dart | 21 ++++++++++ 7 files changed, 94 insertions(+), 50 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33f71044..f00dd055 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# 3.0.4 +* Add `RouteResult` class, which allows segments (i.e. wildcard) to +modify the `tail`. +* Add more wildcard tests. + # 3.0.3 * Support trailing text after parameters with custom Regexes. diff --git a/lib/src/grammar.dart b/lib/src/grammar.dart index 152d73ce..50c7ff78 100644 --- a/lib/src/grammar.dart +++ b/lib/src/grammar.dart @@ -95,8 +95,8 @@ class RouteDefinition { RouteDefinition(this.segments); - Parser> compile() { - Parser> out; + Parser compile() { + Parser out; for (int i = 0; i < segments.length; i++) { var s = segments[i]; @@ -105,7 +105,7 @@ class RouteDefinition { out = s.compile(isLast); else out = s.compileNext( - out.then(match('/')).index(0).cast>(), isLast); + out.then(match('/')).index(0).cast(), isLast); } return out; @@ -113,10 +113,9 @@ class RouteDefinition { } abstract class RouteSegment { - Parser> compile(bool isLast); + Parser compile(bool isLast); - Parser> compileNext( - Parser> p, bool isLast); + Parser compileNext(Parser p, bool isLast); } class SlashSegment implements RouteSegment { @@ -125,14 +124,13 @@ class SlashSegment implements RouteSegment { const SlashSegment(); @override - Parser> compile(bool isLast) { - return match(rgx).map((_) => {}); + Parser compile(bool isLast) { + return match(rgx).map((_) => RouteResult({})); } @override - Parser> compileNext( - Parser> p, bool isLast) { - return p.then(compile(isLast)).index(0).cast>(); + Parser compileNext(Parser p, bool isLast) { + return p.then(compile(isLast)).index(0).cast(); } @override @@ -150,14 +148,13 @@ class ConstantSegment extends RouteSegment { } @override - Parser> compile(bool isLast) { - return match>(text).value((r) => {}); + Parser compile(bool isLast) { + return match(text).map((r) => RouteResult({})); } @override - Parser> compileNext( - Parser> p, bool isLast) { - return p.then(compile(isLast)).index(0).cast>(); + Parser compileNext(Parser p, bool isLast) { + return p.then(compile(isLast)).index(0).cast(); } } @@ -176,22 +173,27 @@ class WildcardSegment extends RouteSegment { return r'[^/]*'; } - Parser> _compile(bool isLast) { - var rgx = RegExp('$pre${_symbol(isLast)}$post'); - return match(rgx); + RegExp _compile(bool isLast) { + return RegExp('$pre(${_symbol(isLast)})$post'); // if (isLast) return match(new RegExp(r'.*')); // return match(new RegExp(r'[^/]*')); } @override - Parser> compile(bool isLast) { - return _compile(isLast).map((r) => {}); + Parser compile(bool isLast) { + return match(_compile(isLast)) + .map((r) => RouteResult({}, tail: r.scanner.lastMatch[1])); } @override - Parser> compileNext( - Parser> p, bool isLast) { - return p.then(_compile(isLast)).index(0).cast>(); + Parser compileNext(Parser p, bool isLast) { + return p.then(compile(isLast)).map((r) { + var items = r.value.cast(); + var a = items[0], b = items[1]; + return a + ..addAll(b?.params ?? {}) + .._setTail(b?.tail); + }); } } @@ -206,16 +208,15 @@ class OptionalSegment extends ParameterSegment { } @override - Parser> compile(bool isLast) { + Parser compile(bool isLast) { return super.compile(isLast).opt(); } @override - Parser> compileNext( - Parser> p, bool isLast) { + Parser compileNext(Parser p, bool isLast) { return p.then(_compile().opt()).map((r) { - if (r.value[1] == null) return r.value[0] as Map; - return (r.value[0] as Map) + if (r.value[1] == null) return r.value[0] as RouteResult; + return (r.value[0] as RouteResult) ..addAll({name: Uri.decodeComponent(r.value[1] as String)}); }); } @@ -240,16 +241,15 @@ class ParameterSegment extends RouteSegment { } @override - Parser> compile(bool isLast) { + Parser compile(bool isLast) { return _compile() - .map>((r) => {name: Uri.decodeComponent(r.value)}); + .map((r) => RouteResult({name: Uri.decodeComponent(r.value)})); } @override - Parser> compileNext( - Parser> p, bool isLast) { + Parser compileNext(Parser p, bool isLast) { return p.then(_compile()).map((r) { - return (r.value[0] as Map) + return (r.value[0] as RouteResult) ..addAll({name: Uri.decodeComponent(r.value[1] as String)}); }); } @@ -273,16 +273,15 @@ class ParsedParameterSegment extends RouteSegment { } @override - Parser> compile(bool isLast) { - return parameter._compile().map( - (r) => {parameter.name: getValue(Uri.decodeComponent(r.span.text))}); + Parser compile(bool isLast) { + return parameter._compile().map((r) => RouteResult( + {parameter.name: getValue(Uri.decodeComponent(r.span.text))})); } @override - Parser> compileNext( - Parser> p, bool isLast) { + Parser compileNext(Parser p, bool isLast) { return p.then(parameter._compile()).map((r) { - return (r.value[0] as Map) + return (r.value[0] as RouteResult) ..addAll({ parameter.name: getValue(Uri.decodeComponent(r.value[1] as String)) }); diff --git a/lib/src/route.dart b/lib/src/route.dart index c17d7891..f981912d 100644 --- a/lib/src/route.dart +++ b/lib/src/route.dart @@ -8,15 +8,14 @@ class Route { final Map> _cache = {}; final RouteDefinition _routeDefinition; String name; - Parser> _parser; + Parser _parser; Route(this.path, {@required this.method, @required this.handlers}) : _routeDefinition = RouteGrammar.routeDefinition .parse(new SpanScanner(path.replaceAll(_straySlashes, ''))) .value { if (_routeDefinition?.segments?.isNotEmpty != true) - _parser = - match>('').value((r) => {}); + _parser = match('').map((r) => RouteResult({})); } factory Route.join(Route a, Route b) { @@ -26,8 +25,7 @@ class Route { method: b.method, handlers: b.handlers); } - Parser> get parser => - _parser ??= _routeDefinition.compile(); + Parser get parser => _parser ??= _routeDefinition.compile(); @override String toString() { @@ -57,3 +55,23 @@ class Route { return b.toString(); } } + +/// The result of matching an individual route. +class RouteResult { + /// The parsed route parameters. + final Map params; + + /// Optional. An explicit "tail" value to set. + String get tail => _tail; + + String _tail; + + RouteResult(this.params, {String tail}) : _tail = tail; + + void _setTail(String v) => _tail ??= v; + + /// Adds parameters. + void addAll(Map map) { + params.addAll(map); + } +} diff --git a/lib/src/router.dart b/lib/src/router.dart index d24c97fe..e36df6f8 100644 --- a/lib/src/router.dart +++ b/lib/src/router.dart @@ -292,9 +292,10 @@ class Router { if (parseResult.successful && scanner.isDone) { var result = new RoutingResult( parseResult: parseResult, - params: parseResult.value, + params: parseResult.value.params, shallowRoute: route, - shallowRouter: this); + shallowRouter: this, + tail: (parseResult.value.tail ?? '') + scanner.rest); out.add(result); success = true; } diff --git a/lib/src/routing_result.dart b/lib/src/routing_result.dart index 91de2e57..0fd415f3 100644 --- a/lib/src/routing_result.dart +++ b/lib/src/routing_result.dart @@ -3,7 +3,7 @@ part of angel_route.src.router; /// Represents a complex result of navigating to a path. class RoutingResult { /// The parse result that matched the given sub-path. - final ParseResult> parseResult; + final ParseResult parseResult; /// A nested instance, if a sub-path was matched. final Iterable> nested; @@ -85,7 +85,7 @@ class RoutingResult { this.nested, this.shallowRoute, this.shallowRouter, - this.tail}) { + @required this.tail}) { this.params.addAll(params ?? {}); } } diff --git a/pubspec.yaml b/pubspec.yaml index bf995998..1a212034 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: angel_route description: A powerful, isomorphic routing library for Dart. It is mainly used in the Angel framework, but can be used in Flutter and on the Web. -version: 3.0.3 +version: 3.0.4 author: Tobe O homepage: https://github.com/angel-dart/angel_route environment: diff --git a/test/wildcard_test.dart b/test/wildcard_test.dart index ac83e346..44434b7a 100644 --- a/test/wildcard_test.dart +++ b/test/wildcard_test.dart @@ -22,4 +22,25 @@ void main() { router.resolveAbsolute('/isnt/she/fierce%20harmonica%solo').first; expect(result.handlers, ['lovely']); }); + + test('tail explicitly set intermediate', () { + var results = router.resolveAbsolute('/songs/in_the/key'); + var result = results.first; + print(results.map((r) => {r.route.path: r.tail})); + expect(result.tail, 'in_the'); + }); + + test('tail explicitly set at end', () { + var results = router.resolveAbsolute('/isnt/she/epic'); + var result = results.first; + print(results.map((r) => {r.route.path: r.tail})); + expect(result.tail, 'epic'); + }); + + test('tail with trailing', () { + var results = router.resolveAbsolute('/isnt/she/epic/fail'); + var result = results.first; + print(results.map((r) => {r.route.path: r.tail})); + expect(result.tail, 'epic/fail'); + }); }