From 639d43f42e42e09becb97c0cf0d6118433356dbb Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sun, 3 Feb 2019 00:33:47 -0500 Subject: [PATCH] 3.0.2 --- CHANGELOG.md | 3 ++ example/main.dart | 11 +++++ lib/src/grammar.dart | 105 ++++++++++++++++++++++++++++++++++++------- pubspec.yaml | 2 +- 4 files changed, 103 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5f08002..be1c2116 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# 3.0.2 +* Support leading and trailing text for both `:parameters` and `*` + # 3.0.1 * Make the callback in `Router.group` generically-typed. diff --git a/example/main.dart b/example/main.dart index 98a471e3..b3d6714a 100644 --- a/example/main.dart +++ b/example/main.dart @@ -5,6 +5,17 @@ import 'package:angel_route/angel_route.dart'; main() { final router = new Router(); + router.get('/whois/~:user', () {}); + + router.get('/wild*', () {}); + + // TODO: Enable trailing after custom RegExp + // router.get('/ordinal/int:n([0-9]+)st', () {}); + + print(router.resolveAbsolute('/whois/~thosakwe').first.allParams); + print(router.resolveAbsolute('/wild_thornberrys').first.route.path); + // print(router.resolveAbsolute('/ordinal/1st').first.allParams); + router.get('/users', () {}); router.post('/users/:id/timeline', (String id) {}); diff --git a/lib/src/grammar.dart b/lib/src/grammar.dart index 219c4ad3..886fc2c8 100644 --- a/lib/src/grammar.dart +++ b/lib/src/grammar.dart @@ -1,23 +1,46 @@ part of angel_route.src.router; class RouteGrammar { - static final RegExp rgx = new RegExp(r'\((.+)\)'); + static const String notSlashRgx = r'([^/]+)'; + //static final RegExp rgx = new RegExp(r'\((.+)\)'); static final Parser notSlash = - match(new RegExp(r'[^/]+')).value((r) => r.span.text); + match(new RegExp(notSlashRgx)).value((r) => r.span.text); - static final Parser regExp = match(new RegExp(r'\((.+)\)')) - .value((r) => new RegExp(r.scanner.lastMatch[1])); + static final Parser regExp = + // TODO: Enable trailing here + // match(new RegExp(r'\(([^)]+)\)([^/]+)?')) + match(new RegExp(r'\(([^)]+)\)')) + .value((r) => r.scanner.lastMatch); - static final Parser parameterName = - match(new RegExp(r':([A-Za-z0-9_]+)')) - .value((r) => r.span.text.substring(1)); + static final Parser parameterName = match( + new RegExp('$notSlashRgx?' r':([A-Za-z0-9_]+)' '$notSlashRgx?')) + .value((r) => r.scanner.lastMatch); static final Parser parameterSegment = chain([ parameterName, match('?').value((r) => true).opt(), regExp.opt(), ]).map((r) { - var s = new ParameterSegment(r.value[0] as String, r.value[2] as RegExp); + var match = r.value[0] as Match; + var rgxMatch = r.value[2] as Match; + RegExp rgx; + + if (rgxMatch != null) { + rgx = RegExp(rgxMatch[1]); + var pre = match[1] ?? ''; + var post = rgxMatch[2] ?? ''; + post += match[3] ?? ''; + if (pre.isNotEmpty || post.isNotEmpty) { + if (rgx != null) { + var pattern = pre + rgx.pattern + post; + rgx = RegExp(pattern); + } else { + rgx = RegExp('$pre$notSlashRgx$post'); + } + } + } + + var s = new ParameterSegment(match[2], rgx); return r.value[1] == true ? new OptionalSegment(s) : s; }); @@ -32,22 +55,39 @@ class RouteGrammar { }); static final Parser wildcardSegment = - match('*').value((r) => new WildcardSegment()); + match(RegExp('$notSlashRgx?' r'\*' '$notSlashRgx?')) + .value((r) { + var m = r.scanner.lastMatch; + var pre = m[1] ?? ''; + var post = m[2] ?? ''; + return new WildcardSegment(pre, post); + }); static final Parser constantSegment = notSlash.map((r) => new ConstantSegment(r.value)); - static final Parser routeSegment = any([ + static final Parser slashSegment = + match(SlashSegment.rgx).map((_) => SlashSegment()); + + static final Parser routeSegment = any([ + //slashSegment, parsedParameterSegment, parameterSegment, wildcardSegment, constantSegment ]); + // static final Parser routeDefinition = routeSegment + // .star() + // .map((r) => new RouteDefinition(r.value ?? [])) + // .surroundedBy(match(RegExp(r'/*')).opt()); + + static final Parser slashes = match(RegExp(r'/*')); + static final Parser routeDefinition = routeSegment - .separatedBy(match('/')) + .separatedBy(slashes) .map((r) => new RouteDefinition(r.value ?? [])) - .surroundedBy(match('/').star().opt()); + .surroundedBy(slashes.opt()); } class RouteDefinition { @@ -79,6 +119,26 @@ abstract class RouteSegment { Parser> p, bool isLast); } +class SlashSegment implements RouteSegment { + static final RegExp rgx = RegExp(r'/+'); + + const SlashSegment(); + + @override + Parser> compile(bool isLast) { + return match(rgx).map((_) => {}); + } + + @override + Parser> compileNext( + Parser> p, bool isLast) { + return p.then(compile(isLast)).index(0).cast>(); + } + + @override + String toString() => 'Slash'; +} + class ConstantSegment extends RouteSegment { final String text; @@ -102,14 +162,25 @@ class ConstantSegment extends RouteSegment { } class WildcardSegment extends RouteSegment { + final String pre, post; + + WildcardSegment(this.pre, this.post); + @override String toString() { return 'Wildcard segment'; } + String _symbol(bool isLast) { + if (isLast) return r'.*'; + return r'[^/]*'; + } + Parser> _compile(bool isLast) { - if (isLast) return match(new RegExp(r'.*')); - return match(new RegExp(r'[^/]*')); + var rgx = RegExp('$pre${_symbol(isLast)}$post'); + return match(rgx); + // if (isLast) return match(new RegExp(r'.*')); + // return match(new RegExp(r'[^/]*')); } @override @@ -164,14 +235,14 @@ class ParameterSegment extends RouteSegment { Parser _compile() { return regExp != null - ? match(regExp).value((r) => r.span.text) + ? match(regExp).value((r) => r.scanner.lastMatch[1]) : RouteGrammar.notSlash; } @override Parser> compile(bool isLast) { - return _compile().map>( - (r) => {name: Uri.decodeComponent(r.span.text)}); + return _compile() + .map>((r) => {name: Uri.decodeComponent(r.value)}); } @override diff --git a/pubspec.yaml b/pubspec.yaml index 4022e571..1f4a0f1c 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.1 +version: 3.0.2 author: Tobe O homepage: https://github.com/angel-dart/angel_route environment: