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

Side by Side Diff: packages/polymer/lib/src/build/common.dart

Issue 2312183003: Removed Polymer from Observatory deps (Closed)
Patch Set: Created 4 years, 3 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
OLDNEW
(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 /// Common methods used by transfomers.
6 library polymer.src.build.common;
7
8 import 'dart:async';
9
10 import 'package:analyzer/src/generated/ast.dart';
11 import 'package:analyzer/src/generated/error.dart';
12 import 'package:analyzer/src/generated/parser.dart';
13 import 'package:analyzer/src/generated/scanner.dart';
14 import 'package:barback/barback.dart';
15 import 'package:code_transformers/messages/build_logger.dart';
16 import 'package:html/dom.dart' show Document;
17 import 'package:html/parser.dart' show HtmlParser;
18 import 'package:observe/transformer.dart' show ObservableTransformer;
19 import 'package:path/path.dart' as path;
20
21 import 'constants.dart';
22 import 'messages.dart';
23
24 export 'constants.dart';
25
26 const _ignoredErrors = const [
27 'unexpected-dash-after-double-dash-in-comment',
28 'unexpected-char-in-comment',
29 ];
30
31 /// Parses an HTML file [contents] and returns a DOM-like tree. Adds emitted
32 /// error/warning to [logger].
33 Document _parseHtml(String contents, String sourcePath, BuildLogger logger,
34 {bool checkDocType: true, bool showWarnings: true}) {
35 // TODO(jmesserly): make HTTP encoding configurable
36 var parser = new HtmlParser(contents,
37 encoding: 'utf8', generateSpans: true, sourceUrl: sourcePath);
38 var document = parser.parse();
39
40 // Note: errors aren't fatal in HTML (unless strict mode is on).
41 // So just print them as warnings.
42 if (showWarnings) {
43 for (var e in parser.errors) {
44 if (_ignoredErrors.contains(e.errorCode)) continue;
45 if (checkDocType || e.errorCode != 'expected-doctype-but-got-start-tag') {
46 logger.warning(HTML5_WARNING.create({'message': e.message}),
47 span: e.span);
48 }
49 }
50 }
51 return document;
52 }
53
54 /// Additional options used by polymer transformers
55 class TransformOptions {
56 /// List of entrypoints paths. The paths are relative to the package root and
57 /// are represented using posix style, which matches the representation used
58 /// in asset ids in barback. If null, anything under 'web/' or 'test/' is
59 /// considered an entry point.
60 final List<String> entryPoints;
61
62 /// Map of stylesheet paths that should or should not be inlined. The paths
63 /// are relative to the package root and are represented using posix style,
64 /// which matches the representation used in asset ids in barback.
65 ///
66 /// There is an additional special key 'default' for the global default.
67 final Map<String, bool> inlineStylesheets;
68
69 /// True to enable Content Security Policy.
70 /// This means the HTML page will not have inlined .js code.
71 final bool contentSecurityPolicy;
72
73 /// True to include the compiled JavaScript directly from the HTML page.
74 /// If enabled this will remove "packages/browser/dart.js" and replace
75 /// `type="application/dart"` scripts with equivalent *.dart.js files.
76 final bool directlyIncludeJS;
77
78 /// Run transformers to create a releasable app. For example, include the
79 /// minified versions of the polyfills rather than the debug versions.
80 final bool releaseMode;
81
82 /// This will make a physical element appear on the page showing build logs.
83 /// It will only appear when ![releaseMode] even if this is true.
84 final bool injectBuildLogsInOutput;
85
86 /// Rules to determine whether to run liner on an html file.
87 // TODO(jmesserly): instead of this flag, we should only run linter on
88 // reachable (entry point+imported) html if deploying. See dartbug.com/17199.
89 final LintOptions lint;
90
91 /// This will automatically inject the polyfills from the `web_components`
92 /// package in all entry points, if it is not already included.
93 final bool injectWebComponentsJs;
94
95 TransformOptions({entryPoints, this.inlineStylesheets,
96 this.contentSecurityPolicy: false, this.directlyIncludeJS: true,
97 this.releaseMode: true, this.lint: const LintOptions(),
98 this.injectBuildLogsInOutput: false, this.injectWebComponentsJs: true})
99 : entryPoints = entryPoints == null
100 ? null
101 : entryPoints.map(systemToAssetPath).toList();
102
103 /// Whether an asset with [id] is an entry point HTML file.
104 bool isHtmlEntryPoint(AssetId id) {
105 if (id.extension != '.html') return false;
106
107 // Note: [id.path] is a relative path from the root of a package.
108 if (entryPoints == null) {
109 return id.path.startsWith('web/') || id.path.startsWith('test/');
110 }
111
112 return entryPoints.contains(id.path);
113 }
114
115 // Whether a stylesheet with [id] should be inlined, the default is true.
116 bool shouldInlineStylesheet(AssetId id) {
117 // Note: [id.path] is a relative path from the root of a package.
118 // Default is to inline everything
119 if (inlineStylesheets == null) return true;
120 // First check for the full asset path overrides.
121 var override = inlineStylesheets[id.toString()];
122 if (override != null) return override;
123 // Then check just the path overrides (if the package was not specified).
124 override = inlineStylesheets[id.path];
125 if (override != null) return override;
126 // Then check the global default setting.
127 var globalDefault = inlineStylesheets['default'];
128 return (globalDefault != null) ? globalDefault : true;
129 }
130
131 // Whether a stylesheet with [id] has an overriden inlining setting.
132 bool stylesheetInliningIsOverridden(AssetId id) {
133 return inlineStylesheets != null &&
134 (inlineStylesheets.containsKey(id.toString()) ||
135 inlineStylesheets.containsKey(id.path));
136 }
137 }
138
139 class LintOptions {
140 /// Whether lint is enabled.
141 final bool enabled;
142
143 /// Patterns explicitly included/excluded from linting (if any).
144 final List<RegExp> patterns;
145
146 /// When [patterns] is not null, whether they denote inclusion or exclusion.
147 final bool isInclude;
148
149 const LintOptions()
150 : enabled = true,
151 patterns = null,
152 isInclude = true;
153
154 const LintOptions.disabled()
155 : enabled = false,
156 patterns = null,
157 isInclude = true;
158
159 LintOptions.include(List<String> patterns)
160 : enabled = true,
161 isInclude = true,
162 patterns = patterns.map((s) => new RegExp(s)).toList();
163
164 LintOptions.exclude(List<String> patterns)
165 : enabled = true,
166 isInclude = false,
167 patterns = patterns.map((s) => new RegExp(s)).toList();
168
169 bool shouldLint(String fileName) {
170 if (!enabled) return false;
171 if (patterns == null) return isInclude;
172 for (var pattern in patterns) {
173 if (pattern.hasMatch(fileName)) return isInclude;
174 }
175 return !isInclude;
176 }
177 }
178
179 /// Mixin for polymer transformers.
180 abstract class PolymerTransformer {
181 TransformOptions get options;
182
183 Future<Document> readPrimaryAsHtml(Transform transform, BuildLogger logger) {
184 var asset = transform.primaryInput;
185 var id = asset.id;
186 return asset.readAsString().then((content) {
187 return _parseHtml(content, id.path, logger,
188 checkDocType: options.isHtmlEntryPoint(id));
189 });
190 }
191
192 Future<Document> readAsHtml(
193 AssetId id, Transform transform, BuildLogger logger,
194 {bool showWarnings: true}) {
195 var primaryId = transform.primaryInput.id;
196 bool samePackage = id.package == primaryId.package;
197 var url = spanUrlFor(id, transform, logger);
198 return transform.readInputAsString(id).then((content) {
199 return _parseHtml(content, url, logger,
200 checkDocType: samePackage && options.isHtmlEntryPoint(id),
201 showWarnings: showWarnings);
202 });
203 }
204
205 Future<bool> assetExists(AssetId id, Transform transform) =>
206 transform.getInput(id).then((_) => true).catchError((_) => false);
207
208 String toString() => 'polymer ($runtimeType)';
209 }
210
211 /// Gets the appropriate URL to use in a span to produce messages (e.g.
212 /// warnings) for users. This will attempt to format the URL in the most useful
213 /// way:
214 ///
215 /// - If the asset is within the primary package, then use the [id.path],
216 /// the user will know it is a file from their own code.
217 /// - If the asset is from another package, then use [assetUrlFor], this will
218 /// likely be a "package:" url to the file in the other package, which is
219 /// enough for users to identify where the error is.
220 String spanUrlFor(AssetId id, Transform transform, logger) {
221 var primaryId = transform.primaryInput.id;
222 bool samePackage = id.package == primaryId.package;
223 return samePackage
224 ? id.path
225 : assetUrlFor(id, primaryId, logger, allowAssetUrl: true);
226 }
227
228 /// Transformer phases which should be applied to the Polymer package.
229 List<List<Transformer>> get phasesForPolymer =>
230 [[new ObservableTransformer(files: ['lib/src/instance.dart'])]];
231
232 /// Generate the import url for a file described by [id], referenced by a file
233 /// with [sourceId].
234 // TODO(sigmund): this should also be in barback (dartbug.com/12610)
235 String assetUrlFor(AssetId id, AssetId sourceId, BuildLogger logger,
236 {bool allowAssetUrl: false}) {
237 // use package: and asset: urls if possible
238 if (id.path.startsWith('lib/')) {
239 return 'package:${id.package}/${id.path.substring(4)}';
240 }
241
242 if (id.path.startsWith('asset/')) {
243 if (!allowAssetUrl) {
244 logger.error(INTERNAL_ERROR_DONT_KNOW_HOW_TO_IMPORT.create({
245 'target': id,
246 'source': sourceId,
247 'extra': ' (asset urls not allowed.)'
248 }));
249 return null;
250 }
251 return 'asset:${id.package}/${id.path.substring(6)}';
252 }
253
254 // Use relative urls only if it's possible.
255 if (id.package != sourceId.package) {
256 logger.error("don't know how to refer to $id from $sourceId");
257 return null;
258 }
259
260 var builder = path.url;
261 return builder.relative(builder.join('/', id.path),
262 from: builder.join('/', builder.dirname(sourceId.path)));
263 }
264
265 /// Convert system paths to asset paths (asset paths are posix style).
266 String systemToAssetPath(String assetPath) {
267 if (path.Style.platform != path.Style.windows) return assetPath;
268 return path.posix.joinAll(path.split(assetPath));
269 }
270
271 /// Returns true if this is a valid custom element name. See:
272 /// <http://w3c.github.io/webcomponents/spec/custom/#dfn-custom-element-type>
273 bool isCustomTagName(String name) {
274 if (name == null || !name.contains('-')) return false;
275 return !invalidTagNames.containsKey(name);
276 }
277
278 /// Regex to split names in the 'attributes' attribute, which supports 'a b c',
279 /// 'a,b,c', or even 'a b,c'. This is the same as in `lib/src/declaration.dart`.
280 final ATTRIBUTES_REGEX = new RegExp(r'\s|,');
OLDNEW
« no previous file with comments | « packages/polymer/lib/src/build/build_log_combiner.dart ('k') | packages/polymer/lib/src/build/constants.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698