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 path.style.url; | 5 library path.style.url; |
6 | 6 |
| 7 import '../characters.dart' as chars; |
7 import '../internal_style.dart'; | 8 import '../internal_style.dart'; |
| 9 import '../utils.dart'; |
8 | 10 |
9 /// The style for URL paths. | 11 /// The style for URL paths. |
10 class UrlStyle extends InternalStyle { | 12 class UrlStyle extends InternalStyle { |
11 UrlStyle(); | 13 UrlStyle(); |
12 | 14 |
13 final name = 'url'; | 15 final name = 'url'; |
14 final separator = '/'; | 16 final separator = '/'; |
| 17 final separators = const ['/']; |
| 18 |
| 19 // Deprecated properties. |
| 20 |
15 final separatorPattern = new RegExp(r'/'); | 21 final separatorPattern = new RegExp(r'/'); |
16 final needsSeparatorPattern = new RegExp( | 22 final needsSeparatorPattern = new RegExp( |
17 r"(^[a-zA-Z][-+.a-zA-Z\d]*://|[^/])$"); | 23 r"(^[a-zA-Z][-+.a-zA-Z\d]*://|[^/])$"); |
18 final rootPattern = new RegExp(r"[a-zA-Z][-+.a-zA-Z\d]*://[^/]*"); | 24 final rootPattern = new RegExp(r"[a-zA-Z][-+.a-zA-Z\d]*://[^/]*"); |
19 final relativeRootPattern = new RegExp(r"^/"); | 25 final relativeRootPattern = new RegExp(r"^/"); |
20 | 26 |
| 27 bool containsSeparator(String path) => path.contains('/'); |
| 28 |
| 29 bool isSeparator(int codeUnit) => codeUnit == chars.SLASH; |
| 30 |
| 31 bool needsSeparator(String path) { |
| 32 if (path.isEmpty) return false; |
| 33 |
| 34 // A URL that doesn't end in "/" always needs a separator. |
| 35 if (!isSeparator(path.codeUnitAt(path.length - 1))) return true; |
| 36 |
| 37 // A URI that's just "scheme://" needs an extra separator, despite ending |
| 38 // with "/". |
| 39 var root = _getRoot(path); |
| 40 return root != null && root.endsWith('://'); |
| 41 } |
| 42 |
| 43 String getRoot(String path) { |
| 44 var root = _getRoot(path); |
| 45 return root == null ? getRelativeRoot(path) : root; |
| 46 } |
| 47 |
| 48 String getRelativeRoot(String path) { |
| 49 if (path.isEmpty) return null; |
| 50 return isSeparator(path.codeUnitAt(0)) ? "/" : null; |
| 51 } |
| 52 |
21 String pathFromUri(Uri uri) => uri.toString(); | 53 String pathFromUri(Uri uri) => uri.toString(); |
22 | 54 |
23 Uri relativePathToUri(String path) => Uri.parse(path); | 55 Uri relativePathToUri(String path) => Uri.parse(path); |
24 Uri absolutePathToUri(String path) => Uri.parse(path); | 56 Uri absolutePathToUri(String path) => Uri.parse(path); |
| 57 |
| 58 // A helper method for [getRoot] that doesn't handle relative roots. |
| 59 String _getRoot(String path) { |
| 60 if (path.isEmpty) return null; |
| 61 |
| 62 // We aren't using a RegExp for this because they're slow (issue 19090). If |
| 63 // we could, we'd match against r"[a-zA-Z][-+.a-zA-Z\d]*://[^/]*". |
| 64 |
| 65 if (!isAlphabetic(path.codeUnitAt(0))) return null; |
| 66 var start = 1; |
| 67 for (; start < path.length; start++) { |
| 68 var char = path.codeUnitAt(start); |
| 69 if (isAlphabetic(char)) continue; |
| 70 if (isNumeric(char)) continue; |
| 71 if (char == chars.MINUS || char == chars.PLUS || char == chars.PERIOD) { |
| 72 continue; |
| 73 } |
| 74 |
| 75 break; |
| 76 } |
| 77 |
| 78 if (start + 3 > path.length) return null; |
| 79 if (path.substring(start, start + 3) != '://') return null; |
| 80 start += 3; |
| 81 |
| 82 // A URL root can end with a non-"/" prefix. |
| 83 while (start < path.length && !isSeparator(path.codeUnitAt(start))) { |
| 84 start++; |
| 85 } |
| 86 return path.substring(0, start); |
| 87 } |
25 } | 88 } |
OLD | NEW |