| 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 |