This commit is contained in:
Tobe O 2019-02-03 00:33:47 -05:00
parent ce59862394
commit 639d43f42e
4 changed files with 103 additions and 18 deletions

View file

@ -1,3 +1,6 @@
# 3.0.2
* Support leading and trailing text for both `:parameters` and `*`
# 3.0.1 # 3.0.1
* Make the callback in `Router.group` generically-typed. * Make the callback in `Router.group` generically-typed.

View file

@ -5,6 +5,17 @@ import 'package:angel_route/angel_route.dart';
main() { main() {
final router = new Router(); 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.get('/users', () {});
router.post('/users/:id/timeline', (String id) {}); router.post('/users/:id/timeline', (String id) {});

View file

@ -1,23 +1,46 @@
part of angel_route.src.router; part of angel_route.src.router;
class RouteGrammar { class RouteGrammar {
static final RegExp rgx = new RegExp(r'\((.+)\)'); static const String notSlashRgx = r'([^/]+)';
//static final RegExp rgx = new RegExp(r'\((.+)\)');
static final Parser<String> notSlash = static final Parser<String> notSlash =
match<String>(new RegExp(r'[^/]+')).value((r) => r.span.text); match<String>(new RegExp(notSlashRgx)).value((r) => r.span.text);
static final Parser<RegExp> regExp = match<RegExp>(new RegExp(r'\((.+)\)')) static final Parser<Match> regExp =
.value((r) => new RegExp(r.scanner.lastMatch[1])); // TODO: Enable trailing here
// match<Match>(new RegExp(r'\(([^)]+)\)([^/]+)?'))
match<Match>(new RegExp(r'\(([^)]+)\)'))
.value((r) => r.scanner.lastMatch);
static final Parser<String> parameterName = static final Parser<Match> parameterName = match<Match>(
match<String>(new RegExp(r':([A-Za-z0-9_]+)')) new RegExp('$notSlashRgx?' r':([A-Za-z0-9_]+)' '$notSlashRgx?'))
.value((r) => r.span.text.substring(1)); .value((r) => r.scanner.lastMatch);
static final Parser<ParameterSegment> parameterSegment = chain([ static final Parser<ParameterSegment> parameterSegment = chain([
parameterName, parameterName,
match<bool>('?').value((r) => true).opt(), match<bool>('?').value((r) => true).opt(),
regExp.opt(), regExp.opt(),
]).map((r) { ]).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; return r.value[1] == true ? new OptionalSegment(s) : s;
}); });
@ -32,22 +55,39 @@ class RouteGrammar {
}); });
static final Parser<WildcardSegment> wildcardSegment = static final Parser<WildcardSegment> wildcardSegment =
match<WildcardSegment>('*').value((r) => new WildcardSegment()); match<WildcardSegment>(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> constantSegment = static final Parser<ConstantSegment> constantSegment =
notSlash.map<ConstantSegment>((r) => new ConstantSegment(r.value)); notSlash.map<ConstantSegment>((r) => new ConstantSegment(r.value));
static final Parser<RouteSegment> routeSegment = any<RouteSegment>([ static final Parser<SlashSegment> slashSegment =
match(SlashSegment.rgx).map((_) => SlashSegment());
static final Parser<RouteSegment> routeSegment = any([
//slashSegment,
parsedParameterSegment, parsedParameterSegment,
parameterSegment, parameterSegment,
wildcardSegment, wildcardSegment,
constantSegment constantSegment
]); ]);
// static final Parser<RouteDefinition> routeDefinition = routeSegment
// .star()
// .map<RouteDefinition>((r) => new RouteDefinition(r.value ?? []))
// .surroundedBy(match(RegExp(r'/*')).opt());
static final Parser slashes = match(RegExp(r'/*'));
static final Parser<RouteDefinition> routeDefinition = routeSegment static final Parser<RouteDefinition> routeDefinition = routeSegment
.separatedBy(match('/')) .separatedBy(slashes)
.map<RouteDefinition>((r) => new RouteDefinition(r.value ?? [])) .map<RouteDefinition>((r) => new RouteDefinition(r.value ?? []))
.surroundedBy(match('/').star().opt()); .surroundedBy(slashes.opt());
} }
class RouteDefinition { class RouteDefinition {
@ -79,6 +119,26 @@ abstract class RouteSegment {
Parser<Map<String, dynamic>> p, bool isLast); Parser<Map<String, dynamic>> p, bool isLast);
} }
class SlashSegment implements RouteSegment {
static final RegExp rgx = RegExp(r'/+');
const SlashSegment();
@override
Parser<Map<String, dynamic>> compile(bool isLast) {
return match(rgx).map((_) => {});
}
@override
Parser<Map<String, dynamic>> compileNext(
Parser<Map<String, dynamic>> p, bool isLast) {
return p.then(compile(isLast)).index(0).cast<Map<String, dynamic>>();
}
@override
String toString() => 'Slash';
}
class ConstantSegment extends RouteSegment { class ConstantSegment extends RouteSegment {
final String text; final String text;
@ -102,14 +162,25 @@ class ConstantSegment extends RouteSegment {
} }
class WildcardSegment extends RouteSegment { class WildcardSegment extends RouteSegment {
final String pre, post;
WildcardSegment(this.pre, this.post);
@override @override
String toString() { String toString() {
return 'Wildcard segment'; return 'Wildcard segment';
} }
String _symbol(bool isLast) {
if (isLast) return r'.*';
return r'[^/]*';
}
Parser<Map<String, dynamic>> _compile(bool isLast) { Parser<Map<String, dynamic>> _compile(bool isLast) {
if (isLast) return match(new RegExp(r'.*')); var rgx = RegExp('$pre${_symbol(isLast)}$post');
return match(new RegExp(r'[^/]*')); return match(rgx);
// if (isLast) return match(new RegExp(r'.*'));
// return match(new RegExp(r'[^/]*'));
} }
@override @override
@ -164,14 +235,14 @@ class ParameterSegment extends RouteSegment {
Parser<String> _compile() { Parser<String> _compile() {
return regExp != null return regExp != null
? match<String>(regExp).value((r) => r.span.text) ? match<String>(regExp).value((r) => r.scanner.lastMatch[1])
: RouteGrammar.notSlash; : RouteGrammar.notSlash;
} }
@override @override
Parser<Map<String, dynamic>> compile(bool isLast) { Parser<Map<String, dynamic>> compile(bool isLast) {
return _compile().map<Map<String, dynamic>>( return _compile()
(r) => {name: Uri.decodeComponent(r.span.text)}); .map<Map<String, dynamic>>((r) => {name: Uri.decodeComponent(r.value)});
} }
@override @override

View file

@ -1,6 +1,6 @@
name: angel_route 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. 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 <thosakwe@gmail.com> author: Tobe O <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/angel_route homepage: https://github.com/angel-dart/angel_route
environment: environment: