feat(transformers): provide a flag to disable inlining views
Add a flag to allow a user to disable inlining css/html content into the views. Closes #2658
This commit is contained in:
parent
34eaf65a79
commit
dcdd73065a
|
@ -10,6 +10,7 @@ const CUSTOM_ANNOTATIONS_PARAM = 'custom_annotations';
|
|||
const ENTRY_POINT_PARAM = 'entry_points';
|
||||
const GENERATE_CHANGE_DETECTORS_PARAM = 'generate_change_detectors';
|
||||
const INIT_REFLECTOR_PARAM = 'init_reflector';
|
||||
const INLINE_VIEWS_PARAM = 'inline_views';
|
||||
const MIRROR_MODE_PARAM = 'mirror_mode';
|
||||
const OPTIMIZATION_PHASES_PARAM = 'optimization_phases';
|
||||
const REFLECTION_ENTRY_POINT_PARAM = 'reflection_entry_points';
|
||||
|
@ -32,6 +33,9 @@ class TransformerOptions {
|
|||
/// Whether to generate calls to our generated `initReflector` code
|
||||
final bool initReflector;
|
||||
|
||||
/// Whether to inline html/css urls into the View directive
|
||||
final bool inlineViews;
|
||||
|
||||
/// The [AnnotationMatcher] which is used to identify angular annotations.
|
||||
final AnnotationMatcher annotationMatcher;
|
||||
|
||||
|
@ -50,13 +54,14 @@ class TransformerOptions {
|
|||
TransformerOptions._internal(this.entryPoints, this.reflectionEntryPoints,
|
||||
this.modeName, this.mirrorMode, this.initReflector,
|
||||
this.annotationMatcher, this.optimizationPhases,
|
||||
this.generateChangeDetectors);
|
||||
this.generateChangeDetectors, this.inlineViews);
|
||||
|
||||
factory TransformerOptions(List<String> entryPoints,
|
||||
{List<String> reflectionEntryPoints, String modeName: 'release',
|
||||
MirrorMode mirrorMode: MirrorMode.none, bool initReflector: true,
|
||||
List<AnnotationDescriptor> customAnnotationDescriptors: const [],
|
||||
int optimizationPhases: DEFAULT_OPTIMIZATION_PHASES,
|
||||
bool inlineViews: true,
|
||||
bool generateChangeDetectors: true}) {
|
||||
if (reflectionEntryPoints == null || reflectionEntryPoints.isEmpty) {
|
||||
reflectionEntryPoints = entryPoints;
|
||||
|
@ -66,6 +71,6 @@ class TransformerOptions {
|
|||
optimizationPhases = optimizationPhases.isNegative ? 0 : optimizationPhases;
|
||||
return new TransformerOptions._internal(entryPoints, reflectionEntryPoints,
|
||||
modeName, mirrorMode, initReflector, annotationMatcher,
|
||||
optimizationPhases, generateChangeDetectors);
|
||||
optimizationPhases, generateChangeDetectors, inlineViews);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ TransformerOptions parseBarbackSettings(BarbackSettings settings) {
|
|||
_readFileList(config, REFLECTION_ENTRY_POINT_PARAM);
|
||||
var initReflector =
|
||||
_readBool(config, INIT_REFLECTOR_PARAM, defaultValue: true);
|
||||
var inlineViews = _readBool(config, INLINE_VIEWS_PARAM, defaultValue: true);
|
||||
var generateChangeDetectors =
|
||||
_readBool(config, GENERATE_CHANGE_DETECTORS_PARAM, defaultValue: true);
|
||||
String mirrorModeVal =
|
||||
|
@ -35,6 +36,7 @@ TransformerOptions parseBarbackSettings(BarbackSettings settings) {
|
|||
modeName: settings.mode.name,
|
||||
mirrorMode: mirrorMode,
|
||||
initReflector: initReflector,
|
||||
inlineViews: inlineViews,
|
||||
customAnnotationDescriptors: _readCustomAnnotations(config),
|
||||
optimizationPhases: optimizationPhases,
|
||||
generateChangeDetectors: generateChangeDetectors);
|
||||
|
|
|
@ -23,12 +23,12 @@ import 'visitors.dart';
|
|||
/// string unless `forceGenerate` is true, in which case an empty ngDeps
|
||||
/// file is created.
|
||||
Future<String> createNgDeps(AssetReader reader, AssetId assetId,
|
||||
AnnotationMatcher annotationMatcher) async {
|
||||
AnnotationMatcher annotationMatcher, bool inlineViews) async {
|
||||
// TODO(kegluneq): Shortcut if we can determine that there are no
|
||||
// [Directive]s present, taking into account `export`s.
|
||||
var writer = new AsyncStringWriter();
|
||||
var visitor = new CreateNgDepsVisitor(
|
||||
writer, assetId, new XhrImpl(reader, assetId), annotationMatcher);
|
||||
var visitor = new CreateNgDepsVisitor(writer, assetId,
|
||||
new XhrImpl(reader, assetId), annotationMatcher, inlineViews);
|
||||
var code = await reader.readAsString(assetId);
|
||||
parseCompilationUnit(code, name: assetId.path).accept(visitor);
|
||||
|
||||
|
@ -60,13 +60,14 @@ class CreateNgDepsVisitor extends Object with SimpleAstVisitor<Object> {
|
|||
/// The assetId for the file which we are parsing.
|
||||
final AssetId assetId;
|
||||
|
||||
CreateNgDepsVisitor(
|
||||
AsyncStringWriter writer, this.assetId, XHR xhr, this._annotationMatcher)
|
||||
CreateNgDepsVisitor(AsyncStringWriter writer, this.assetId, XHR xhr,
|
||||
this._annotationMatcher, inlineViews)
|
||||
: writer = writer,
|
||||
_copyVisitor = new ToSourceVisitor(writer),
|
||||
_factoryVisitor = new FactoryTransformVisitor(writer),
|
||||
_paramsVisitor = new ParameterTransformVisitor(writer),
|
||||
_metaVisitor = new AnnotationsTransformVisitor(writer, xhr);
|
||||
_metaVisitor = new AnnotationsTransformVisitor(
|
||||
writer, xhr, inlineViews);
|
||||
|
||||
void _visitNodeListWithSeparator(NodeList<AstNode> list, String separator) {
|
||||
if (list == null) return;
|
||||
|
|
|
@ -34,8 +34,8 @@ class DirectiveProcessor extends Transformer {
|
|||
try {
|
||||
var asset = transform.primaryInput;
|
||||
var reader = new AssetReader.fromTransform(transform);
|
||||
var ngDepsSrc =
|
||||
await createNgDeps(reader, asset.id, options.annotationMatcher);
|
||||
var ngDepsSrc = await createNgDeps(
|
||||
reader, asset.id, options.annotationMatcher, options.inlineViews);
|
||||
if (ngDepsSrc != null && ngDepsSrc.isNotEmpty) {
|
||||
var ngDepsAssetId =
|
||||
transform.primaryInput.id.changeExtension(DEPS_EXTENSION);
|
||||
|
|
|
@ -211,10 +211,12 @@ bool _isViewAnnotation(Annotation node) => '${node.name}' == 'View';
|
|||
class AnnotationsTransformVisitor extends ToSourceVisitor {
|
||||
final AsyncStringWriter writer;
|
||||
final XHR _xhr;
|
||||
final bool _inlineViews;
|
||||
final ConstantEvaluator _evaluator = new ConstantEvaluator();
|
||||
bool _processingView = false;
|
||||
|
||||
AnnotationsTransformVisitor(AsyncStringWriter writer, this._xhr)
|
||||
AnnotationsTransformVisitor(
|
||||
AsyncStringWriter writer, this._xhr, this._inlineViews)
|
||||
: this.writer = writer,
|
||||
super(writer);
|
||||
|
||||
|
@ -259,32 +261,34 @@ class AnnotationsTransformVisitor extends ToSourceVisitor {
|
|||
return super.visitNamedExpression(node);
|
||||
}
|
||||
var keyString = '${node.name.label}';
|
||||
if (keyString == 'templateUrl') {
|
||||
// Inline the templateUrl
|
||||
var url = node.expression.accept(_evaluator);
|
||||
if (url is String) {
|
||||
writer.print("template: r'''");
|
||||
writer.asyncPrint(_readOrEmptyString(url));
|
||||
writer.print("'''");
|
||||
return null;
|
||||
} else {
|
||||
logger.warning('template url is not a String $url');
|
||||
}
|
||||
} else if (keyString == 'styleUrls') {
|
||||
// Inline the styleUrls
|
||||
var urls = node.expression.accept(_evaluator);
|
||||
writer.print('styles: const [');
|
||||
for (var url in urls) {
|
||||
if (_inlineViews) {
|
||||
if (keyString == 'templateUrl') {
|
||||
// Inline the templateUrl
|
||||
var url = node.expression.accept(_evaluator);
|
||||
if (url is String) {
|
||||
writer.print("r'''");
|
||||
writer.print("template: r'''");
|
||||
writer.asyncPrint(_readOrEmptyString(url));
|
||||
writer.print("''', ");
|
||||
writer.print("'''");
|
||||
return null;
|
||||
} else {
|
||||
logger.warning('style url is not a String ${url}');
|
||||
logger.warning('template url is not a String $url');
|
||||
}
|
||||
} else if (keyString == 'styleUrls') {
|
||||
// Inline the styleUrls
|
||||
var urls = node.expression.accept(_evaluator);
|
||||
writer.print('styles: const [');
|
||||
for (var url in urls) {
|
||||
if (url is String) {
|
||||
writer.print("r'''");
|
||||
writer.asyncPrint(_readOrEmptyString(url));
|
||||
writer.print("''', ");
|
||||
} else {
|
||||
logger.warning('style url is not a String ${url}');
|
||||
}
|
||||
}
|
||||
writer.print(']');
|
||||
return null;
|
||||
}
|
||||
writer.print(']');
|
||||
return null;
|
||||
}
|
||||
return super.visitNamedExpression(node);
|
||||
}
|
||||
|
|
|
@ -58,6 +58,17 @@ void allTests() {
|
|||
'should inline multiple `styleUrls` values expressed as absolute urls.',
|
||||
'multiple_style_urls_files/hello.dart');
|
||||
|
||||
absoluteReader.addAsset(new AssetId('a', 'lib/template.html'),
|
||||
readFile('directive_processor/multiple_style_urls_files/template.html'));
|
||||
absoluteReader.addAsset(new AssetId('a', 'lib/template.css'),
|
||||
readFile('directive_processor/multiple_style_urls_files/template.css'));
|
||||
absoluteReader.addAsset(new AssetId('a', 'lib/template_other.css'), readFile(
|
||||
'directive_processor/multiple_style_urls_files/template_other.css'));
|
||||
_testNgDeps(
|
||||
'shouldn\'t inline multiple `styleUrls` values expressed as absolute '
|
||||
'urls.', 'multiple_style_urls_not_inlined_files/hello.dart',
|
||||
inlineViews: false, reader: absoluteReader);
|
||||
|
||||
_testNgDeps('should inline `templateUrl`s expressed as adjacent strings.',
|
||||
'split_url_expression_files/hello.dart');
|
||||
|
||||
|
@ -86,7 +97,7 @@ void allTests() {
|
|||
|
||||
void _testNgDeps(String name, String inputPath,
|
||||
{List<AnnotationDescriptor> customDescriptors: const [], AssetId assetId,
|
||||
AssetReader reader, List<String> expectedLogs}) {
|
||||
AssetReader reader, List<String> expectedLogs, bool inlineViews: true}) {
|
||||
it(name, () async {
|
||||
if (expectedLogs != null) {
|
||||
log.setLogger(new RecordingLogger());
|
||||
|
@ -105,7 +116,8 @@ void _testNgDeps(String name, String inputPath,
|
|||
var expectedId = _assetIdForPath(expectedPath);
|
||||
|
||||
var annotationMatcher = new AnnotationMatcher()..addAll(customDescriptors);
|
||||
var output = await createNgDeps(reader, inputId, annotationMatcher);
|
||||
var output =
|
||||
await createNgDeps(reader, inputId, annotationMatcher, inlineViews);
|
||||
if (output == null) {
|
||||
expect(await reader.hasInput(expectedId)).toBeFalse();
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
library examples.src.hello_world.index_common_dart.ng_deps.dart;
|
||||
|
||||
import 'hello.dart';
|
||||
import 'package:angular2/angular2.dart'
|
||||
show bootstrap, Component, Directive, View, NgElement;
|
||||
|
||||
var _visited = false;
|
||||
void initReflector(reflector) {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
reflector
|
||||
..registerType(HelloCmp, {
|
||||
'factory': () => new HelloCmp(),
|
||||
'parameters': const [],
|
||||
'annotations': const [
|
||||
const Component(selector: 'hello-app'),
|
||||
const View(
|
||||
template: r'''{{greeting}}''',
|
||||
styles: const [
|
||||
r'''.greeting { .color: blue; }''',
|
||||
r'''.hello { .color: red; }''',
|
||||
])
|
||||
]
|
||||
});
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
library examples.src.hello_world.index_common_dart.ng_deps.dart;
|
||||
|
||||
import 'hello.dart';
|
||||
import 'package:angular2/angular2.dart'
|
||||
show bootstrap, Component, Directive, View, NgElement;
|
||||
|
||||
var _visited = false;
|
||||
void initReflector(reflector) {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
reflector
|
||||
..registerType(HelloCmp, {
|
||||
'factory': () => new HelloCmp(),
|
||||
'parameters': const [],
|
||||
'annotations': const [
|
||||
const Component(selector: 'hello-app'),
|
||||
const View(
|
||||
templateUrl: 'package:a/template.html',
|
||||
styleUrls: const [
|
||||
'package:a/template.css',
|
||||
'package:a/template_other.css'
|
||||
])
|
||||
]
|
||||
});
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
library examples.src.hello_world.index_common_dart;
|
||||
|
||||
import 'package:angular2/angular2.dart'
|
||||
show bootstrap, Component, Directive, View, NgElement;
|
||||
|
||||
@Component(selector: 'hello-app')
|
||||
@View(
|
||||
templateUrl: 'package:a/template.html',
|
||||
styleUrls: const ['package:a/template.css', 'package:a/template_other.css'])
|
||||
class HelloCmp {}
|
|
@ -0,0 +1 @@
|
|||
.greeting { .color: blue; }
|
|
@ -0,0 +1 @@
|
|||
{{greeting}}
|
|
@ -0,0 +1 @@
|
|||
.hello { .color: red; }
|
Loading…
Reference in New Issue