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 |