| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library route.url_pattern; | 5 library route.url_pattern; |
| 6 | 6 |
| 7 import 'url_matcher.dart'; | 7 import 'url_matcher.dart'; |
| 8 | 8 |
| 9 // From the PatternCharacter rule here: | 9 // From the PatternCharacter rule here: |
| 10 // http://ecma-international.org/ecma-262/5.1/#sec-15.10 | 10 // http://ecma-international.org/ecma-262/5.1/#sec-15.10 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 * server.dart: | 46 * server.dart: |
| 47 * | 47 * |
| 48 * import 'urls.dart'; | 48 * import 'urls.dart'; |
| 49 * import 'package:route/server.dart'; | 49 * import 'package:route/server.dart'; |
| 50 * | 50 * |
| 51 * main() { | 51 * main() { |
| 52 * var server = new HttpServer(); | 52 * var server = new HttpServer(); |
| 53 * server.addRequestHandler(matchesUrl(articleUrl), serveArticle); | 53 * server.addRequestHandler(matchesUrl(articleUrl), serveArticle); |
| 54 * } | 54 * } |
| 55 * | 55 * |
| 56 * serveArcticle(req, res) { | 56 * serveArticle(req, res) { |
| 57 * var articleId = articleUrl.parse(req.path)[0]; | 57 * var articleId = articleUrl.parse(req.path)[0]; |
| 58 * // ... | 58 * // ... |
| 59 * } | 59 * } |
| 60 * | 60 * |
| 61 * Use with older browsers | 61 * Use with older browsers |
| 62 * ----------------------- | 62 * ----------------------- |
| 63 * | 63 * |
| 64 * Since '#' matches both '#' and '/' it can be used in as a path separator | 64 * Since '#' matches both '#' and '/' it can be used in as a path separator |
| 65 * between the "static" portion of your URL and the "dynamic" portion. The | 65 * between the "static" portion of your URL and the "dynamic" portion. The |
| 66 * dynamic portion would be the part that change when a user navigates to new | 66 * dynamic portion would be the part that change when a user navigates to new |
| (...skipping 20 matching lines...) Expand all Loading... |
| 87 RegExp _baseRegex; | 87 RegExp _baseRegex; |
| 88 | 88 |
| 89 UrlPattern(this.pattern) { | 89 UrlPattern(this.pattern) { |
| 90 _parse(pattern); | 90 _parse(pattern); |
| 91 } | 91 } |
| 92 | 92 |
| 93 RegExp get regex => _regex; | 93 RegExp get regex => _regex; |
| 94 | 94 |
| 95 String reverse(Iterable args, {bool useFragment: false}) { | 95 String reverse(Iterable args, {bool useFragment: false}) { |
| 96 var sb = new StringBuffer(); | 96 var sb = new StringBuffer(); |
| 97 var chars = pattern.split(''); | |
| 98 var argsIter = args.iterator; | 97 var argsIter = args.iterator; |
| 99 | 98 |
| 100 int depth = 0; | 99 int depth = 0; |
| 101 int groupCount = 0; | 100 int groupCount = 0; |
| 102 bool escaped = false; | 101 bool escaped = false; |
| 103 | 102 |
| 104 for (int i = 0; i < chars.length; i++) { | 103 for (int i = 0; i < pattern.length; i++) { |
| 105 var c = chars[i]; | 104 var c = pattern[i]; |
| 106 if (c == '\\' && escaped == false) { | 105 if (c == '\\' && escaped == false) { |
| 107 escaped = true; | 106 escaped = true; |
| 108 } else { | 107 } else { |
| 109 if (c == '(') { | 108 if (c == '(') { |
| 110 if (escaped && depth == 0) { | 109 if (escaped && depth == 0) { |
| 111 sb.write(c); | 110 sb.write(c); |
| 112 } | 111 } |
| 113 if (!escaped) depth++; | 112 if (!escaped) depth++; |
| 114 } else if (c == ')') { | 113 } else if (c == ')') { |
| 115 if (escaped && depth == 0) { | 114 if (escaped && depth == 0) { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 /** | 190 /** |
| 192 * Returns true if the path portion of the pattern, the part before the | 191 * Returns true if the path portion of the pattern, the part before the |
| 193 * fragment, matches [str]. If there is no fragment in the pattern, this is | 192 * fragment, matches [str]. If there is no fragment in the pattern, this is |
| 194 * equivalent to calling [matches]. | 193 * equivalent to calling [matches]. |
| 195 * | 194 * |
| 196 * This method is most useful on a server that is serving the HTML of a | 195 * This method is most useful on a server that is serving the HTML of a |
| 197 * single page app. Clients that don't support pushState will not send the | 196 * single page app. Clients that don't support pushState will not send the |
| 198 * fragment to the server, so the server will have to handle just the path | 197 * fragment to the server, so the server will have to handle just the path |
| 199 * part. | 198 * part. |
| 200 */ | 199 */ |
| 201 bool matchesNonFragment(String str) { | 200 bool matchesNonFragment(String str) => |
| 202 if (!_hasFragment) { | 201 _hasFragment ? _matches(_baseRegex, str) : matches(str); |
| 203 return matches(str); | |
| 204 } else { | |
| 205 return _matches(_baseRegex, str); | |
| 206 } | |
| 207 } | |
| 208 | 202 |
| 209 Iterable<Match> allMatches(String str) { | 203 Iterable<Match> allMatches(String str) => regex.allMatches(str); |
| 210 return regex.allMatches(str); | |
| 211 } | |
| 212 | 204 |
| 213 bool operator ==(other) => | 205 bool operator ==(other) => |
| 214 (other is UrlPattern) && (other.pattern == pattern); | 206 (other is UrlPattern) && (other.pattern == pattern); |
| 215 | 207 |
| 216 int get hashCode => pattern.hashCode; | 208 int get hashCode => pattern.hashCode; |
| 217 | 209 |
| 218 String toString() => pattern.toString(); | 210 String toString() => pattern.toString(); |
| 219 | 211 |
| 220 _parse(String pattern) { | 212 _parse(String pattern) { |
| 221 var sb = new StringBuffer(); | 213 var sb = new StringBuffer(); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 lastGroupEnd = i; | 265 lastGroupEnd = i; |
| 274 } | 266 } |
| 275 } else if (c == '#') { | 267 } else if (c == '#') { |
| 276 // TODO(justinfagnani): what else should be banned in groups? '/'? | 268 // TODO(justinfagnani): what else should be banned in groups? '/'? |
| 277 throw new ArgumentError('illegal # inside group'); | 269 throw new ArgumentError('illegal # inside group'); |
| 278 } | 270 } |
| 279 escaped = (c == r'\' && !escaped); | 271 escaped = (c == r'\' && !escaped); |
| 280 sb.write(c); | 272 sb.write(c); |
| 281 } | 273 } |
| 282 } | 274 } |
| 283 // sb.write(r'$'); | |
| 284 _regex = new RegExp(sb.toString()); | 275 _regex = new RegExp(sb.toString()); |
| 285 } | 276 } |
| 286 | 277 |
| 287 void _setBasePattern(String basePattern) { | 278 void _setBasePattern(String basePattern) { |
| 288 if (_hasFragment == true) { | 279 if (_hasFragment == true) { |
| 289 throw new ArgumentError('multiple # characters'); | 280 throw new ArgumentError('multiple # characters'); |
| 290 } | 281 } |
| 291 _hasFragment = true; | 282 _hasFragment = true; |
| 292 _baseRegex = new RegExp('$basePattern\$'); | 283 _baseRegex = new RegExp('$basePattern\$'); |
| 293 } | 284 } |
| 294 | 285 |
| 295 Match matchAsPrefix(String string, [int start = 0]) { | 286 Match matchAsPrefix(String string, [int start = 0]) { |
| 296 throw new UnimplementedError('matchAsPrefix is not implemented'); | 287 throw new UnimplementedError('matchAsPrefix is not implemented'); |
| 297 } | 288 } |
| 298 | 289 |
| 299 List<String> urlParameterNames() { | 290 List<String> urlParameterNames() { |
| 300 throw new UnimplementedError('urlParameterNames is not implemented'); | 291 throw new UnimplementedError('urlParameterNames is not implemented'); |
| 301 } | 292 } |
| 302 | 293 |
| 303 int compareTo(UrlMatcher another) { | 294 int compareTo(UrlMatcher another) { |
| 304 throw new UnimplementedError('compareTo is not implemented'); | 295 throw new UnimplementedError('compareTo is not implemented'); |
| 305 } | 296 } |
| 306 } | 297 } |
| OLD | NEW |