OLD | NEW |
(Empty) | |
| 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 |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 /** |
| 6 * Holds path information that is used by the WebUI compiler to find files, |
| 7 * compute their output location and relative paths between them. |
| 8 */ |
| 9 library polymer.src.paths; |
| 10 |
| 11 import 'info.dart' show UrlInfo; |
| 12 import 'messages.dart'; |
| 13 import 'summary.dart'; |
| 14 import 'utils.dart' show path, pathToUrl; |
| 15 |
| 16 /** |
| 17 * Stores information about paths and computes mappings between input and output |
| 18 * path locations. |
| 19 */ |
| 20 class PathMapper { |
| 21 /** |
| 22 * Common prefix to all input paths that are read from the file system. The |
| 23 * output generated by the compiler will reflect the directory structure |
| 24 * starting from [_baseDir]. For instance, if [_baseDir] is `a/b/c` and |
| 25 * [_outputDir] is `g/h/`, then the corresponding output file for |
| 26 * `a/b/c/e/f.html` will be under `g/h/e/f.html.dart`. |
| 27 */ |
| 28 final String _baseDir; |
| 29 |
| 30 /** Base path where all output is generated. */ |
| 31 final String _outputDir; |
| 32 |
| 33 /** The package root directory. */ |
| 34 final String packageRoot; |
| 35 |
| 36 /** Whether to add prefixes and to output file names. */ |
| 37 final bool _mangleFilenames; |
| 38 |
| 39 final bool _rewriteUrls; |
| 40 |
| 41 bool get _rewritePackageImports => _rewriteUrls || !_mangleFilenames; |
| 42 |
| 43 /** Default prefix added to all filenames. */ |
| 44 static const String _DEFAULT_PREFIX = '_'; |
| 45 |
| 46 PathMapper(String baseDir, String outputDir, this.packageRoot, |
| 47 bool forceMangle, this._rewriteUrls) |
| 48 : _baseDir = baseDir, |
| 49 _outputDir = outputDir, |
| 50 _mangleFilenames = forceMangle || (baseDir == outputDir); |
| 51 |
| 52 /** Add a prefix and [suffix] if [_mangleFilenames] is true */ |
| 53 String mangle(String name, String suffix, [bool forceSuffix = false]) => |
| 54 _mangleFilenames ? "$_DEFAULT_PREFIX$name$suffix" |
| 55 : (forceSuffix ? "$name$suffix" : name); |
| 56 |
| 57 /** |
| 58 * Checks that `input.resolvedPath` is a valid input path. It must be in |
| 59 * [_baseDir] and must not be in the [_outputDir]. If not, an error message |
| 60 * is added to [messages]. |
| 61 */ |
| 62 bool checkInputPath(UrlInfo input, Messages messages) { |
| 63 if (_mangleFilenames) return true; |
| 64 var canonicalized = path.normalize(input.resolvedPath); |
| 65 var parentDir = '..${path.separator}'; |
| 66 if (!path.relative(canonicalized, from: _outputDir).startsWith(parentDir)) { |
| 67 messages.error( |
| 68 'The file ${input.resolvedPath} cannot be processed. ' |
| 69 'Files cannot be under the output folder (${_outputDir}).', |
| 70 input.sourceSpan); |
| 71 return false; |
| 72 } |
| 73 if (path.relative(canonicalized, from: _baseDir).startsWith(parentDir)) { |
| 74 messages.error( |
| 75 'The file ${input.resolvedPath} cannot be processed. ' |
| 76 'All processed files must be under the base folder (${_baseDir}), you' |
| 77 ' can specify the base folder using the --basedir flag.', |
| 78 input.sourceSpan); |
| 79 return false; |
| 80 } |
| 81 return true; |
| 82 } |
| 83 |
| 84 /** |
| 85 * The path to the output file corresponding to [input], by adding |
| 86 * [_DEFAULT_PREFIX] and a [suffix] to its file name. |
| 87 */ |
| 88 String outputPath(String input, String suffix, [bool forceSuffix = false]) => |
| 89 path.join(outputDirPath(input), |
| 90 mangle(path.basename(input), suffix, forceSuffix)); |
| 91 |
| 92 /** The path to the output file corresponding to [info]. */ |
| 93 String outputLibraryPath(LibrarySummary lib) => |
| 94 path.join(outputDirPath(lib.dartCodeUrl.resolvedPath), |
| 95 lib.outputFilename); |
| 96 |
| 97 /** The corresponding output directory for [input]'s directory. */ |
| 98 String outputDirPath(String input) { |
| 99 return _rewritePackages(path.normalize( |
| 100 path.join(_outputDir, path.relative( |
| 101 path.dirname(input), from: _baseDir)))); |
| 102 } |
| 103 |
| 104 /** |
| 105 * We deal with `packages/` directories in a very special way. We assume it |
| 106 * points to resources loaded from other pub packages. If an output directory |
| 107 * is specified, the compiler will create a packages symlink so that |
| 108 * `package:` imports work. |
| 109 * |
| 110 * To make it possible to share components through pub, we allow using tags of |
| 111 * the form `<link rel="import" href="packages/...">`, so that you can |
| 112 * refer to components within the packages symlink. Regardless of whether an |
| 113 * --out option was given to the compiler, we don't want to generate files |
| 114 * inside `packages/` for those components. Instead we will generate such |
| 115 * code in a special directory called `_from_packages/`. |
| 116 */ |
| 117 String _rewritePackages(String outputPath) { |
| 118 // TODO(jmesserly): this should match against packageRoot instead. |
| 119 if (!outputPath.contains('packages')) return outputPath; |
| 120 if (!_rewritePackageImports) return outputPath; |
| 121 var segments = path.split(outputPath); |
| 122 return path.joinAll( |
| 123 segments.map((s) => s == 'packages' ? '_from_packages' : s)); |
| 124 } |
| 125 |
| 126 /** |
| 127 * Returns a url to import/export the output library represented by [target] |
| 128 * from the output library of [src]. In other words, a url to import or export |
| 129 * `target.outputFilename` from `src.outputFilename`. |
| 130 */ |
| 131 String importUrlFor(LibrarySummary src, LibrarySummary target) { |
| 132 if (!_rewritePackageImports && |
| 133 target.dartCodeUrl.url.startsWith('package:')) { |
| 134 return pathToUrl(path.join(path.dirname(target.dartCodeUrl.url), |
| 135 target.outputFilename)); |
| 136 } |
| 137 var srcDir = path.dirname(src.dartCodeUrl.resolvedPath); |
| 138 var relDir = path.relative( |
| 139 path.dirname(target.dartCodeUrl.resolvedPath), from: srcDir); |
| 140 return pathToUrl(_rewritePackages(path.normalize( |
| 141 path.join(relDir, target.outputFilename)))); |
| 142 } |
| 143 |
| 144 /** |
| 145 * Transforms a [target] url seen in [src] (e.g. a Dart import, a .css href in |
| 146 * an HTML file, etc) into a corresponding url from the output file associated |
| 147 * with [src]. This will keep 'package:', 'dart:', path-absolute, and absolute |
| 148 * urls intact, but it will fix relative paths to walk from the output |
| 149 * directory back to the input directory. An exception will be thrown if |
| 150 * [target] is not under [_baseDir]. |
| 151 */ |
| 152 String transformUrl(String src, String target) { |
| 153 var uri = Uri.parse(target); |
| 154 if (uri.isAbsolute) return target; |
| 155 if (!uri.scheme.isEmpty) return target; |
| 156 if (!uri.host.isEmpty) return target; |
| 157 if (uri.path.isEmpty) return target; // Implies standalone ? or # in URI. |
| 158 if (path.isAbsolute(target)) return target; |
| 159 |
| 160 return pathToUrl(path.normalize(path.relative( |
| 161 path.join(path.dirname(src), target), from: outputDirPath(src)))); |
| 162 } |
| 163 } |
| 164 |
| 165 /** |
| 166 * Returns a "mangled" name, with a prefix and [suffix] depending on the |
| 167 * compiler's settings. [forceSuffix] causes [suffix] to be appended even if |
| 168 * the compiler is not mangling names. |
| 169 */ |
| 170 typedef String NameMangler(String name, String suffix, [bool forceSuffix]); |
OLD | NEW |