Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(38)

Side by Side Diff: lib/src/template/dartio_stub.dart

Issue 11092092: Support compiling templates in the browser. Base URL: git@github.com:dart-lang/dart-web-components.git@master
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/src/template/compile.dart ('k') | lib/src/template/emitters.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
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.
4
5 /**
6 * This library contains stubs for dartio functionality useful in the browser.
7 * Contents of this file were directly copied from dart:io.
8 */
9 // TODO(jacobr): remove when there is a subset of dart:io that runs client and
10 // server. b/5818
11 library dartio_stub;
12
13 /**
14 * A Path, which is a String interpreted as a sequence of path segments,
15 * which are strings, separated by forward slashes.
16 * Paths are immutable wrappers of a String, that offer member functions for
17 * useful path manipulations and queries. Joining of paths and normalization
18 * interpret '.' and '..' in the usual way.
19 */
20 abstract class Path {
21 /**
22 * Creates a Path from the String [source]. [source] is used as-is, so if
23 * the string does not consist of segments separated by forward slashes, the
24 * behavior may not be as expected. Paths are immutable.
25 */
26 factory Path(String source) => new _Path(source);
27
28 /**
29 * Creates a Path from a String that uses the native filesystem's conventions.
30 * On Windows, this converts '\' to '/', and adds a '/' before a drive letter.
31 * A path starting with '/c:/' (or any other character instead of 'c') is
32 * treated specially. Backwards links ('..') cannot cancel the drive letter.
33 */
34 factory Path.fromNative(String source) => new _Path.fromNative(source);
35
36 /**
37 * Is this path the empty string?
38 */
39 bool get isEmpty;
40
41 /**
42 * Is this path an absolute path, beginning with a path separator?
43 */
44 bool get isAbsolute;
45
46 /**
47 * Does this path end with a path separator?
48 */
49 bool get hasTrailingSeparator;
50
51 /**
52 * Does this path contain no consecutive path separators, no segments that
53 * are '.' unless the path is exactly '.', and segments that are '..' only
54 * as the leading segments on a relative path?
55 */
56 bool get isCanonical;
57
58 /**
59 * Make a path canonical by dropping segments that are '.', cancelling
60 * segments that are '..' with preceding segments, if possible,
61 * and combining consecutive path separators. Leading '..' segments
62 * are kept on relative paths, and dropped from absolute paths.
63 */
64 Path canonicalize();
65
66 /**
67 * Joins the relative path [further] to this path. Canonicalizes the
68 * resulting joined path using [canonicalize],
69 * interpreting '.' and '..' as directory traversal commands, and removing
70 * consecutive path separators.
71 *
72 * If [further] is an absolute path, an IllegalArgument exception is thrown.
73 *
74 * Examples:
75 * `new Path('/a/b/c').join(new Path('d/e'))` returns the Path object
76 * containing `'a/b/c/d/e'`.
77 *
78 * `new Path('a/b/../c/').join(new Path('d/./e//')` returns the Path
79 * containing `'a/c/d/e/'`.
80 *
81 * `new Path('a/b/c').join(new Path('d/../../e')` returns the Path
82 * containing `'a/b/e'`.
83 *
84 * Note that the join operation does not drop the last segment of the
85 * base path, the way URL joining does. That would be accomplished with
86 * basepath.directoryPath.join(further).
87 *
88 * If you want to avoid joins that traverse
89 * parent directories in the base, you can check whether
90 * `further.canonicalize()` starts with '../' or equals '..'.
91 */
92 Path join(Path further);
93
94
95 /**
96 * Returns a path [:relative:] such that
97 * [:base.join(relative) == this.canonicalize():].
98 * Throws an exception if such a path is impossible.
99 * For example, if [base] is '../../a/b' and [this] is '.'.
100 * The computation is independent of the file system and current directory.
101 */
102 Path relativeTo(Path base);
103
104 /**
105 * Converts a path to a string using the native filesystem's conventions.
106 *
107 * On Windows, converts path separators to backwards slashes, and removes
108 * the leading path separator if the path starts with a drive specification.
109 * For most valid Windows paths, this should be the inverse of the
110 * constructor Path.fromNative.
111 */
112 String toNativePath();
113
114 /**
115 * Returns the path as a string. If this path is constructed using
116 * new Path() or new Path.fromNative() on a non-Windows system, the
117 * returned value is the original string argument to the constructor.
118 */
119 String toString();
120
121 /**
122 * Gets the segments of a Path. Paths beginning or ending with the
123 * path separator do not have leading or terminating empty segments.
124 * Other than that, the segments are just the result of splitting the
125 * path on the path separator.
126 *
127 * new Path('/a/b/c/d').segments() == ['a', 'b', 'c', d'];
128 * new Path(' foo bar //../') == [' foo bar ', '', '..'];
129 */
130 List<String> segments();
131
132 /**
133 * Appends [finalSegment] to a path as a new segment. Adds a path separator
134 * between the path and [finalSegment] if the path does not already end in
135 * a path separator. The path is not canonicalized, and [finalSegment] may
136 * contain path separators.
137 */
138 Path append(String finalSegment);
139
140 /**
141 * Drops the final path separator and whatever follows it from this Path,
142 * and returns the resulting Path object. If the only path separator in
143 * this Path is the first character, returns '/' instead of the empty string.
144 * If there is no path separator in the Path, returns the empty string.
145 *
146 * new Path('../images/dot.gif').directoryPath == '../images'
147 * new Path('/usr/geoffrey/www/').directoryPath == '/usr/geoffrey/www'
148 * new Path('lost_file_old').directoryPath == ''
149 * new Path('/src').directoryPath == '/'
150 * Note: new Path('/D:/src').directoryPath == '/D:'
151 */
152 Path get directoryPath;
153
154 /**
155 * The part of the path after the last path separator, or the entire path if
156 * it contains no path separator.
157 *
158 * new Path('images/DSC_0027.jpg).filename == 'DSC_0027.jpg'
159 * new Path('users/fred/').filename == ''
160 */
161 String get filename;
162
163 /**
164 * The part of [filename] before the last '.', or the entire filename if it
165 * contains no '.'. If [filename] is '.' or '..' it is unchanged.
166 *
167 * new Path('/c:/My Documents/Heidi.txt').filenameWithoutExtension
168 * would return 'Heidi'.
169 * new Path('not what I would call a path').filenameWithoutExtension
170 * would return 'not what I would call a path'.
171 */
172 String get filenameWithoutExtension;
173
174 /**
175 * The part of [filename] after the last '.', or '' if [filename]
176 * contains no '.'. If [filename] is '.' or '..', returns ''.
177 *
178 * new Path('tiger.svg').extension == 'svg'
179 * new Path('/src/dart/dart_secrets').extension == ''
180 */
181 String get extension;
182 }
183
184 class _Path implements Path {
185 final String _path;
186
187 _Path(String source) : _path = source;
188 _Path.fromNative(String source) : _path = _clean(source);
189
190 int hashCode() => _path.hashCode();
191
192 static String _clean(String source) {
193 switch (Platform.operatingSystem) {
194 case 'windows':
195 return _cleanWindows(source);
196 default:
197 return source;
198 }
199 }
200
201 static String _cleanWindows(source) {
202 // Change \ to /.
203 var clean = source.replaceAll('\\', '/');
204 // Add / before intial [Drive letter]:
205 if (clean.length >= 2 && clean[1] == ':') {
206 clean = '/$clean';
207 }
208 return clean;
209 }
210
211 bool get isEmpty => _path.isEmpty();
212 bool get isAbsolute => _path.startsWith('/');
213 bool get hasTrailingSeparator => _path.endsWith('/');
214
215 String toString() => _path;
216
217 Path relativeTo(Path base) {
218 // Throws exception if an unimplemented or impossible case is reached.
219 // Returns a path "relative" such that
220 // base.join(relative) == this.canonicalize.
221 // Throws an exception if no such path exists, or the case is not
222 // implemented yet.
223 if (base.isAbsolute && _path.startsWith(base._path)) {
224 if (_path == base._path) return new Path('.');
225 if (base.hasTrailingSeparator) {
226 return new Path(_path.substring(base._path.length));
227 }
228 if (_path[base._path.length] == '/') {
229 return new Path(_path.substring(base._path.length + 1));
230 }
231 }
232 throw new NotImplementedException(
233 "Unimplemented case of Path.relativeTo(base):\n"
234 " Only absolute paths with strict containment are handled at present.\n"
235 " Arguments: $_path.relativeTo($base)");
236 }
237
238 Path join(Path further) {
239 if (further.isAbsolute) {
240 throw new ArgumentError(
241 "Path.join called with absolute Path as argument.");
242 }
243 if (isEmpty) {
244 return further.canonicalize();
245 }
246 if (hasTrailingSeparator) {
247 return new Path('$_path${further._path}').canonicalize();
248 }
249 return new Path('$_path/${further._path}').canonicalize();
250 }
251
252 // Note: The URI RFC names for these operations are normalize, resolve, and
253 // relativize.
254 Path canonicalize() {
255 if (isCanonical) return this;
256 return makeCanonical();
257 }
258
259 bool get isCanonical {
260 // Contains no consecutive path separators.
261 // Contains no segments that are '.'.
262 // Absolute paths have no segments that are '..'.
263 // All '..' segments of a relative path are at the beginning.
264 if (isEmpty) return false; // The canonical form of '' is '.'.
265 if (_path == '.') return true;
266 List segs = _path.split('/'); // Don't mask the getter 'segments'.
267 if (segs[0] == '') { // Absolute path
268 segs[0] = null; // Faster than removeRange().
269 } else { // A canonical relative path may start with .. segments.
270 for (int pos = 0;
271 pos < segs.length && segs[pos] == '..';
272 ++pos) {
273 segs[pos] = null;
274 }
275 }
276 if (segs.last() == '') segs.removeLast(); // Path ends with /.
277 // No remaining segments can be ., .., or empty.
278 return !segs.some((s) => s == '' || s == '.' || s == '..');
279 }
280
281 Path makeCanonical() {
282 bool isAbs = isAbsolute;
283 List segs = segments();
284 String drive;
285 if (isAbs &&
286 !segs.isEmpty() &&
287 segs[0].length == 2 &&
288 segs[0][1] == ':') {
289 drive = segs[0];
290 segs.removeRange(0, 1);
291 }
292 List newSegs = [];
293 for (String segment in segs) {
294 switch (segment) {
295 case '..':
296 // Absolute paths drop leading .. markers, including after a drive.
297 if (newSegs.isEmpty()) {
298 if (isAbs) {
299 // Do nothing: drop the segment.
300 } else {
301 newSegs.add('..');
302 }
303 } else if (newSegs.last() == '..') {
304 newSegs.add('..');
305 } else {
306 newSegs.removeLast();
307 }
308 break;
309 case '.':
310 case '':
311 // Do nothing - drop the segment.
312 break;
313 default:
314 newSegs.add(segment);
315 break;
316 }
317 }
318
319 List segmentsToJoin = [];
320 if (isAbs) {
321 segmentsToJoin.add('');
322 if (drive != null) {
323 segmentsToJoin.add(drive);
324 }
325 }
326
327 if (newSegs.isEmpty()) {
328 if (isAbs) {
329 segmentsToJoin.add('');
330 } else {
331 segmentsToJoin.add('.');
332 }
333 } else {
334 segmentsToJoin.addAll(newSegs);
335 if (hasTrailingSeparator) {
336 segmentsToJoin.add('');
337 }
338 }
339 return new Path(Strings.join(segmentsToJoin, '/'));
340 }
341
342 String toNativePath() {
343 return _path;
344 }
345
346 List<String> segments() {
347 List result = _path.split('/');
348 if (isAbsolute) result.removeRange(0, 1);
349 if (hasTrailingSeparator) result.removeLast();
350 return result;
351 }
352
353 Path append(String finalSegment) {
354 if (isEmpty) {
355 return new Path(finalSegment);
356 } else if (hasTrailingSeparator) {
357 return new Path('$_path$finalSegment');
358 } else {
359 return new Path('$_path/$finalSegment');
360 }
361 }
362
363 String get filenameWithoutExtension {
364 var name = filename;
365 if (name == '.' || name == '..') return name;
366 int pos = name.lastIndexOf('.');
367 return (pos < 0) ? name : name.substring(0, pos);
368 }
369
370 String get extension {
371 var name = filename;
372 int pos = name.lastIndexOf('.');
373 return (pos < 0) ? '' : name.substring(pos + 1);
374 }
375
376 Path get directoryPath {
377 int pos = _path.lastIndexOf('/');
378 if (pos < 0) return new Path('');
379 while (pos > 0 && _path[pos - 1] == '/') --pos;
380 return new Path((pos > 0) ? _path.substring(0, pos) : '/');
381 }
382
383 String get filename {
384 int pos = _path.lastIndexOf('/');
385 return _path.substring(pos + 1);
386 }
387 }
388
389
OLDNEW
« no previous file with comments | « lib/src/template/compile.dart ('k') | lib/src/template/emitters.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698