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

Unified Diff: observatory_pub_packages/polymer/src/build/common.dart

Issue 816693004: Add observatory_pub_packages snapshot to third_party (Closed) Base URL: http://dart.googlecode.com/svn/third_party/
Patch Set: Created 6 years 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 side-by-side diff with in-line comments
Download patch
Index: observatory_pub_packages/polymer/src/build/common.dart
===================================================================
--- observatory_pub_packages/polymer/src/build/common.dart (revision 0)
+++ observatory_pub_packages/polymer/src/build/common.dart (working copy)
@@ -0,0 +1,273 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Common methods used by transfomers.
+library polymer.src.build.common;
+
+import 'dart:async';
+
+import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/parser.dart';
+import 'package:analyzer/src/generated/scanner.dart';
+import 'package:barback/barback.dart';
+import 'package:code_transformers/messages/build_logger.dart';
+import 'package:html5lib/dom.dart' show Document;
+import 'package:html5lib/parser.dart' show HtmlParser;
+import 'package:observe/transformer.dart' show ObservableTransformer;
+import 'package:path/path.dart' as path;
+
+import 'constants.dart';
+import 'messages.dart';
+
+export 'constants.dart';
+
+const _ignoredErrors = const [
+ 'unexpected-dash-after-double-dash-in-comment',
+ 'unexpected-char-in-comment',
+];
+
+/// Parses an HTML file [contents] and returns a DOM-like tree. Adds emitted
+/// error/warning to [logger].
+Document _parseHtml(String contents, String sourcePath, BuildLogger logger,
+ {bool checkDocType: true, bool showWarnings: true}) {
+ // TODO(jmesserly): make HTTP encoding configurable
+ var parser = new HtmlParser(contents, encoding: 'utf8',
+ generateSpans: true, sourceUrl: sourcePath);
+ var document = parser.parse();
+
+ // Note: errors aren't fatal in HTML (unless strict mode is on).
+ // So just print them as warnings.
+ if (showWarnings) {
+ for (var e in parser.errors) {
+ if (_ignoredErrors.contains(e.errorCode)) continue;
+ if (checkDocType || e.errorCode != 'expected-doctype-but-got-start-tag') {
+ logger.warning(HTML5_WARNING.create({'message': e.message}),
+ span: e.span);
+ }
+ }
+ }
+ return document;
+}
+
+/// Additional options used by polymer transformers
+class TransformOptions {
+ /// List of entrypoints paths. The paths are relative to the package root and
+ /// are represented using posix style, which matches the representation used
+ /// in asset ids in barback. If null, anything under 'web/' or 'test/' is
+ /// considered an entry point.
+ final List<String> entryPoints;
+
+ /// Map of stylesheet paths that should or should not be inlined. The paths
+ /// are relative to the package root and are represented using posix style,
+ /// which matches the representation used in asset ids in barback.
+ ///
+ /// There is an additional special key 'default' for the global default.
+ final Map<String, bool> inlineStylesheets;
+
+ /// True to enable Content Security Policy.
+ /// This means the HTML page will not have inlined .js code.
+ final bool contentSecurityPolicy;
+
+ /// True to include the compiled JavaScript directly from the HTML page.
+ /// If enabled this will remove "packages/browser/dart.js" and replace
+ /// `type="application/dart"` scripts with equivalent *.dart.js files.
+ final bool directlyIncludeJS;
+
+ /// Run transformers to create a releasable app. For example, include the
+ /// minified versions of the polyfills rather than the debug versions.
+ final bool releaseMode;
+
+ /// This will make a physical element appear on the page showing build logs.
+ /// It will only appear when ![releaseMode] even if this is true.
+ final bool injectBuildLogsInOutput;
+
+ /// Rules to determine whether to run liner on an html file.
+ // TODO(jmesserly): instead of this flag, we should only run linter on
+ // reachable (entry point+imported) html if deploying. See dartbug.com/17199.
+ final LintOptions lint;
+
+ /// This will automatically inject the polyfills from the `web_components`
+ /// package in all entry points, if it is not already included.
+ final bool injectWebComponentsJs;
+
+ TransformOptions({entryPoints, this.inlineStylesheets,
+ this.contentSecurityPolicy: false, this.directlyIncludeJS: true,
+ this.releaseMode: true, this.lint: const LintOptions(),
+ this.injectBuildLogsInOutput: false, this.injectWebComponentsJs: true})
+ : entryPoints = entryPoints == null ? null
+ : entryPoints.map(systemToAssetPath).toList();
+
+ /// Whether an asset with [id] is an entry point HTML file.
+ bool isHtmlEntryPoint(AssetId id) {
+ if (id.extension != '.html') return false;
+
+ // Note: [id.path] is a relative path from the root of a package.
+ if (entryPoints == null) {
+ return id.path.startsWith('web/') || id.path.startsWith('test/');
+ }
+
+ return entryPoints.contains(id.path);
+ }
+
+ // Whether a stylesheet with [id] should be inlined, the default is true.
+ bool shouldInlineStylesheet(AssetId id) {
+ // Note: [id.path] is a relative path from the root of a package.
+ // Default is to inline everything
+ if (inlineStylesheets == null) return true;
+ // First check for the full asset path overrides.
+ var override = inlineStylesheets[id.toString()];
+ if (override != null) return override;
+ // Then check just the path overrides (if the package was not specified).
+ override = inlineStylesheets[id.path];
+ if (override != null) return override;
+ // Then check the global default setting.
+ var globalDefault = inlineStylesheets['default'];
+ return (globalDefault != null) ? globalDefault : true;
+ }
+
+ // Whether a stylesheet with [id] has an overriden inlining setting.
+ bool stylesheetInliningIsOverridden(AssetId id) {
+ return inlineStylesheets != null &&
+ (inlineStylesheets.containsKey(id.toString())
+ || inlineStylesheets.containsKey(id.path));
+ }
+}
+
+class LintOptions {
+ /// Whether lint is enabled.
+ final bool enabled;
+
+ /// Patterns explicitly included/excluded from linting (if any).
+ final List<RegExp> patterns;
+
+ /// When [patterns] is not null, whether they denote inclusion or exclusion.
+ final bool isInclude;
+
+ const LintOptions()
+ : enabled = true, patterns = null, isInclude = true;
+ const LintOptions.disabled()
+ : enabled = false, patterns = null, isInclude = true;
+
+ LintOptions.include(List<String> patterns)
+ : enabled = true,
+ isInclude = true,
+ patterns = patterns.map((s) => new RegExp(s)).toList();
+
+ LintOptions.exclude(List<String> patterns)
+ : enabled = true,
+ isInclude = false,
+ patterns = patterns.map((s) => new RegExp(s)).toList();
+
+ bool shouldLint(String fileName) {
+ if (!enabled) return false;
+ if (patterns == null) return isInclude;
+ for (var pattern in patterns) {
+ if (pattern.hasMatch(fileName)) return isInclude;
+ }
+ return !isInclude;
+ }
+}
+
+/// Mixin for polymer transformers.
+abstract class PolymerTransformer {
+ TransformOptions get options;
+
+ Future<Document> readPrimaryAsHtml(Transform transform, BuildLogger logger) {
+ var asset = transform.primaryInput;
+ var id = asset.id;
+ return asset.readAsString().then((content) {
+ return _parseHtml(content, id.path, logger,
+ checkDocType: options.isHtmlEntryPoint(id));
+ });
+ }
+
+ Future<Document> readAsHtml(AssetId id, Transform transform,
+ BuildLogger logger,
+ {bool showWarnings: true}) {
+ var primaryId = transform.primaryInput.id;
+ bool samePackage = id.package == primaryId.package;
+ var url = spanUrlFor(id, transform, logger);
+ return transform.readInputAsString(id).then((content) {
+ return _parseHtml(content, url, logger,
+ checkDocType: samePackage && options.isHtmlEntryPoint(id),
+ showWarnings: showWarnings);
+ });
+ }
+
+ Future<bool> assetExists(AssetId id, Transform transform) =>
+ transform.getInput(id).then((_) => true).catchError((_) => false);
+
+ String toString() => 'polymer ($runtimeType)';
+}
+
+/// Gets the appropriate URL to use in a span to produce messages (e.g.
+/// warnings) for users. This will attempt to format the URL in the most useful
+/// way:
+///
+/// - If the asset is within the primary package, then use the [id.path],
+/// the user will know it is a file from their own code.
+/// - If the asset is from another package, then use [assetUrlFor], this will
+/// likely be a "package:" url to the file in the other package, which is
+/// enough for users to identify where the error is.
+String spanUrlFor(AssetId id, Transform transform, logger) {
+ var primaryId = transform.primaryInput.id;
+ bool samePackage = id.package == primaryId.package;
+ return samePackage ? id.path
+ : assetUrlFor(id, primaryId, logger, allowAssetUrl: true);
+}
+
+/// Transformer phases which should be applied to the Polymer package.
+List<List<Transformer>> get phasesForPolymer =>
+ [[new ObservableTransformer(['lib/src/instance.dart'])]];
+
+/// Generate the import url for a file described by [id], referenced by a file
+/// with [sourceId].
+// TODO(sigmund): this should also be in barback (dartbug.com/12610)
+String assetUrlFor(AssetId id, AssetId sourceId, BuildLogger logger,
+ {bool allowAssetUrl: false}) {
+ // use package: and asset: urls if possible
+ if (id.path.startsWith('lib/')) {
+ return 'package:${id.package}/${id.path.substring(4)}';
+ }
+
+ if (id.path.startsWith('asset/')) {
+ if (!allowAssetUrl) {
+ logger.error(INTERNAL_ERROR_DONT_KNOW_HOW_TO_IMPORT.create({
+ 'target': id,
+ 'source': sourceId,
+ 'extra': ' (asset urls not allowed.)'}));
+ return null;
+ }
+ return 'asset:${id.package}/${id.path.substring(6)}';
+ }
+
+ // Use relative urls only if it's possible.
+ if (id.package != sourceId.package) {
+ logger.error("don't know how to refer to $id from $sourceId");
+ return null;
+ }
+
+ var builder = path.url;
+ return builder.relative(builder.join('/', id.path),
+ from: builder.join('/', builder.dirname(sourceId.path)));
+}
+
+
+/// Convert system paths to asset paths (asset paths are posix style).
+String systemToAssetPath(String assetPath) {
+ if (path.Style.platform != path.Style.windows) return assetPath;
+ return path.posix.joinAll(path.split(assetPath));
+}
+
+/// Returns true if this is a valid custom element name. See:
+/// <http://w3c.github.io/webcomponents/spec/custom/#dfn-custom-element-type>
+bool isCustomTagName(String name) {
+ if (name == null || !name.contains('-')) return false;
+ return !invalidTagNames.containsKey(name);
+}
+
+/// Regex to split names in the 'attributes' attribute, which supports 'a b c',
+/// 'a,b,c', or even 'a b,c'. This is the same as in `lib/src/declaration.dart`.
+final ATTRIBUTES_REGEX = new RegExp(r'\s|,');

Powered by Google App Engine
This is Rietveld 408576698