From dcdd73065a6c77c1425e319e12a5c655b6799d7c Mon Sep 17 00:00:00 2001 From: Ted Sander Date: Sat, 20 Jun 2015 18:09:23 -0700 Subject: [PATCH] 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 --- .../src/transform/common/options.dart | 9 +++- .../src/transform/common/options_reader.dart | 2 + .../directive_processor/rewriter.dart | 13 ++--- .../directive_processor/transformer.dart | 4 +- .../directive_processor/visitors.dart | 48 ++++++++++--------- .../directive_processor/all_tests.dart | 16 ++++++- .../expected/hello.ng_deps.dart | 25 ++++++++++ .../expected/hello.ng_deps.dart | 25 ++++++++++ .../hello.dart | 10 ++++ .../template.css | 1 + .../template.html | 1 + .../template_other.css | 1 + 12 files changed, 121 insertions(+), 34 deletions(-) create mode 100644 modules/angular2/test/transform/directive_processor/expected/hello.ng_deps.dart create mode 100644 modules/angular2/test/transform/directive_processor/multiple_style_urls_not_inlined_files/expected/hello.ng_deps.dart create mode 100644 modules/angular2/test/transform/directive_processor/multiple_style_urls_not_inlined_files/hello.dart create mode 100644 modules/angular2/test/transform/directive_processor/multiple_style_urls_not_inlined_files/template.css create mode 100644 modules/angular2/test/transform/directive_processor/multiple_style_urls_not_inlined_files/template.html create mode 100644 modules/angular2/test/transform/directive_processor/multiple_style_urls_not_inlined_files/template_other.css diff --git a/modules/angular2/src/transform/common/options.dart b/modules/angular2/src/transform/common/options.dart index da296c6eab..5dacca27d3 100644 --- a/modules/angular2/src/transform/common/options.dart +++ b/modules/angular2/src/transform/common/options.dart @@ -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 entryPoints, {List reflectionEntryPoints, String modeName: 'release', MirrorMode mirrorMode: MirrorMode.none, bool initReflector: true, List 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); } } diff --git a/modules/angular2/src/transform/common/options_reader.dart b/modules/angular2/src/transform/common/options_reader.dart index 56c3e661aa..fea17511a1 100644 --- a/modules/angular2/src/transform/common/options_reader.dart +++ b/modules/angular2/src/transform/common/options_reader.dart @@ -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); diff --git a/modules/angular2/src/transform/directive_processor/rewriter.dart b/modules/angular2/src/transform/directive_processor/rewriter.dart index 88ece1c4da..4f47004ab8 100644 --- a/modules/angular2/src/transform/directive_processor/rewriter.dart +++ b/modules/angular2/src/transform/directive_processor/rewriter.dart @@ -23,12 +23,12 @@ import 'visitors.dart'; /// string unless `forceGenerate` is true, in which case an empty ngDeps /// file is created. Future 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 { /// 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 list, String separator) { if (list == null) return; diff --git a/modules/angular2/src/transform/directive_processor/transformer.dart b/modules/angular2/src/transform/directive_processor/transformer.dart index 211800a190..e26f05e366 100644 --- a/modules/angular2/src/transform/directive_processor/transformer.dart +++ b/modules/angular2/src/transform/directive_processor/transformer.dart @@ -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); diff --git a/modules/angular2/src/transform/directive_processor/visitors.dart b/modules/angular2/src/transform/directive_processor/visitors.dart index 46ec758ee5..6108ac8fdc 100644 --- a/modules/angular2/src/transform/directive_processor/visitors.dart +++ b/modules/angular2/src/transform/directive_processor/visitors.dart @@ -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); } diff --git a/modules/angular2/test/transform/directive_processor/all_tests.dart b/modules/angular2/test/transform/directive_processor/all_tests.dart index f81f7db4dc..953c9fdd02 100644 --- a/modules/angular2/test/transform/directive_processor/all_tests.dart +++ b/modules/angular2/test/transform/directive_processor/all_tests.dart @@ -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 customDescriptors: const [], AssetId assetId, - AssetReader reader, List expectedLogs}) { + AssetReader reader, List 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 { diff --git a/modules/angular2/test/transform/directive_processor/expected/hello.ng_deps.dart b/modules/angular2/test/transform/directive_processor/expected/hello.ng_deps.dart new file mode 100644 index 0000000000..52e10e3aff --- /dev/null +++ b/modules/angular2/test/transform/directive_processor/expected/hello.ng_deps.dart @@ -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; }''', + ]) + ] + }); +} diff --git a/modules/angular2/test/transform/directive_processor/multiple_style_urls_not_inlined_files/expected/hello.ng_deps.dart b/modules/angular2/test/transform/directive_processor/multiple_style_urls_not_inlined_files/expected/hello.ng_deps.dart new file mode 100644 index 0000000000..d54d5c3ebf --- /dev/null +++ b/modules/angular2/test/transform/directive_processor/multiple_style_urls_not_inlined_files/expected/hello.ng_deps.dart @@ -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' + ]) + ] + }); +} diff --git a/modules/angular2/test/transform/directive_processor/multiple_style_urls_not_inlined_files/hello.dart b/modules/angular2/test/transform/directive_processor/multiple_style_urls_not_inlined_files/hello.dart new file mode 100644 index 0000000000..9fff519f49 --- /dev/null +++ b/modules/angular2/test/transform/directive_processor/multiple_style_urls_not_inlined_files/hello.dart @@ -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 {} diff --git a/modules/angular2/test/transform/directive_processor/multiple_style_urls_not_inlined_files/template.css b/modules/angular2/test/transform/directive_processor/multiple_style_urls_not_inlined_files/template.css new file mode 100644 index 0000000000..c48477652e --- /dev/null +++ b/modules/angular2/test/transform/directive_processor/multiple_style_urls_not_inlined_files/template.css @@ -0,0 +1 @@ +.greeting { .color: blue; } \ No newline at end of file diff --git a/modules/angular2/test/transform/directive_processor/multiple_style_urls_not_inlined_files/template.html b/modules/angular2/test/transform/directive_processor/multiple_style_urls_not_inlined_files/template.html new file mode 100644 index 0000000000..d75013393f --- /dev/null +++ b/modules/angular2/test/transform/directive_processor/multiple_style_urls_not_inlined_files/template.html @@ -0,0 +1 @@ +{{greeting}} \ No newline at end of file diff --git a/modules/angular2/test/transform/directive_processor/multiple_style_urls_not_inlined_files/template_other.css b/modules/angular2/test/transform/directive_processor/multiple_style_urls_not_inlined_files/template_other.css new file mode 100644 index 0000000000..e461b8ddde --- /dev/null +++ b/modules/angular2/test/transform/directive_processor/multiple_style_urls_not_inlined_files/template_other.css @@ -0,0 +1 @@ +.hello { .color: red; } \ No newline at end of file