blob: e18bcf635d4c449e0ffcb6fc8692210dfb1860f5 [file] [log] [blame]
// Copyright (c) 2015, 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.
/// Transformer used for pub serve and pub build
library web_components.transformer;
import 'package:barback/barback.dart';
export 'build/html_import_annotation_recorder.dart';
import 'build/import_inliner.dart';
export 'build/import_inliner.dart';
import 'build/script_compactor.dart';
export 'build/script_compactor.dart';
import 'build/web_components.dart';
export 'build/web_components.dart';
/// The Web Components transformer group, which internally runs several phases
/// that:
/// * Extract inlined script tags into separate files.
/// * Extract script tags from entry points and all html imports and add them
/// as dart imports in a new *.bootstrap.dart file.
/// * Run the `initialize` transformer.
/// * Inlines @HtmlImport annotations as html imports into the entry point.
/// * Inline imported html files and remove all but the main dart script tag.
/// At the end of these phases, this tranformer produces a single entrypoint
/// HTML file with a single Dart script that can later be compiled with dart2js.
class WebComponentsTransformerGroup implements TransformerGroup {
final Iterable<Iterable> phases;
WebComponentsTransformerGroup(TransformOptions options)
: phases = createDeployPhases(options);
WebComponentsTransformerGroup.asPlugin(BarbackSettings settings)
: this(_parseSettings(settings));
/// Create deploy phases for web_components.
List<List<Transformer>> createDeployPhases(TransformOptions options,
{String sdkDir}) {
var phases = [];
// Must happen before the WebComponents transformer, grabs all dart scripts
// and combines them into one bootstrap file.
phases.add([new ScriptCompactorTransformer(options.entryPoints)]);
// Runs the customized version of the `initialize` transformer and inlines
// @HtmlImport annotations.
phases.add([new WebComponentsTransformer(options)]);
// Inlines all html imports and removes all dart script tags in the process.
phases.add([new ImportInlinerTransformer(options.entryPoints)]);
return phases;
/// Options used by web_components 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, any html file under 'web/' or 'test/' is
/// considered an entry point.
final List<String> entryPoints;
/// Current Barback mode.
final bool releaseMode;
TransformOptions(this.entryPoints, this.releaseMode);
/// 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);
// Builds TransformOptions given some BarbackSettings
TransformOptions _parseSettings(BarbackSettings settings) {
var args = settings.configuration;
bool releaseMode = settings.mode == BarbackMode.RELEASE;
var entryPoints = readFileList(args['entry_points']);
return new TransformOptions(entryPoints, releaseMode);
/// Reads a file list value from the [BarbackSettings]
/// TODO(jakemac): This should also move to code_transformers.
readFileList(value) {
if (value == null) return null;
var files = [];
bool error;
if (value is List) {
files = value;
error = value.any((e) => e is! String);
} else if (value is String) {
files = [value];
error = false;
} else {
error = true;
if (error) {
print('Bad value for "entry_points" in the web_components transformer. '
'Expected either one String or a list of Strings.');
return files;