refactor(transformer): precompile stylesheets

Part of #3605
This commit is contained in:
Yegor Jbanov
2015-09-29 17:27:44 -07:00
committed by Tobias Bosch
parent 52236bd765
commit 841f8789fd
10 changed files with 771 additions and 17 deletions

View File

@ -0,0 +1,37 @@
library angular2.transform.stylesheet_compiler.processor;
import 'dart:async';
import 'package:angular2/src/transform/common/asset_reader.dart';
import 'package:angular2/src/transform/common/code/source_module.dart';
import 'package:angular2/src/transform/common/names.dart';
import 'package:angular2/src/transform/common/ng_compiler.dart';
import 'package:angular2/src/compiler/source_module.dart';
import 'package:barback/barback.dart';
AssetId shimmedStylesheetAssetId(AssetId cssAssetId) => new AssetId(
cssAssetId.package, toShimmedStylesheetExtension(cssAssetId.path));
AssetId nonShimmedStylesheetAssetId(AssetId cssAssetId) => new AssetId(
cssAssetId.package, toNonShimmedStylesheetExtension(cssAssetId.path));
Future<Iterable<Asset>> processStylesheet(
AssetReader reader, AssetId stylesheetId) async {
final stylesheetUrl = '${stylesheetId.package}|${stylesheetId.path}';
final templateCompiler = createTemplateCompiler(reader);
final cssText = await reader.readAsString(stylesheetId);
final sourceModules =
templateCompiler.compileStylesheetCodeGen(stylesheetUrl, cssText);
var libraryIdx = 0;
return sourceModules.map((SourceModule module) => new Asset.fromString(
new AssetId.parse('${module.moduleUrl}'),
writeSourceModule(module,
libraryName: '${_getLibBase(module.moduleUrl)}${libraryIdx++}')));
}
final _unsafeCharsPattern = new RegExp(r'[^a-zA-Z0-9_]');
String _getLibBase(String libraryName) {
return libraryName.replaceAll('/', '.').replaceAll(_unsafeCharsPattern, '_');
}

View File

@ -0,0 +1,40 @@
library angular2.transform.stylesheet_compiler.transformer;
import 'dart:async';
import 'package:angular2/src/core/dom/html_adapter.dart';
import 'package:angular2/src/transform/common/asset_reader.dart';
import 'package:angular2/src/transform/common/logging.dart' as log;
import 'package:angular2/src/transform/common/names.dart';
import 'package:barback/barback.dart';
import 'processor.dart';
/// Pre-compiles CSS stylesheet files to Dart code for Angular 2.
class StylesheetCompiler extends Transformer implements DeclaringTransformer {
StylesheetCompiler();
@override
bool isPrimary(AssetId id) {
return id.path.endsWith(CSS_EXTENSION);
}
@override
declareOutputs(DeclaringTransform transform) {
transform.declareOutput(nonShimmedStylesheetAssetId(transform.primaryId));
transform.declareOutput(shimmedStylesheetAssetId(transform.primaryId));
}
@override
Future apply(Transform transform) async {
await log.initZoned(transform, () async {
Html5LibDomAdapter.makeCurrent();
var reader = new AssetReader.fromTransform(transform);
var outputs = await processStylesheet(reader, transform.primaryInput.id);
outputs.forEach((Asset compiledStylesheet) {
transform.addOutput(compiledStylesheet);
});
});
}
}

View File

@ -0,0 +1,23 @@
name: ng2_transform
version: 0.0.0
environment:
sdk: '>=1.8.0 <2.0.0'
dependencies:
angular2:
path: ../../dist/dart/angular2
analyzer: '>=0.24.4 <0.27.0'
barback: '^0.15.2+2'
code_transformers: '^0.2.8'
dart_style: '>=0.1.8 <0.3.0'
glob: '^1.0.0'
guinness: any
html: '^0.12.0'
intl: '^0.12.4'
logging: '>=0.9.0 <0.12.0'
observe: '^0.13.1'
protobuf: '^0.4.2'
quiver: '^0.21.4'
source_span: '^1.0.0'
stack_trace: '^1.1.1'
dev_dependencies:
test: '>=0.12.0 <0.13.0'

View File

@ -0,0 +1,96 @@
library angular2.test.transform.stylesheet_compiler.all_tests;
import 'dart:async';
import 'dart:convert';
import 'package:angular2/src/transform/stylesheet_compiler/transformer.dart';
import 'package:barback/barback.dart';
import 'package:guinness/guinness.dart';
const SIMPLE_CSS = '''
.foo {
width: 10px;
}
''';
main() {
Html5LibDomAdapter.makeCurrent();
allTests();
}
allTests() {
StylesheetCompiler subject;
beforeEach(() {
subject = new StylesheetCompiler();
});
it('should accept CSS assets', () {
expect(subject.isPrimary(new AssetId('somepackage', 'lib/style.css')))
.toBe(true);
});
it('should reject non-CSS assets', () {
expect(subject.isPrimary(new AssetId('somepackage', 'lib/style.scss')))
.toBe(false);
});
it('should declare outputs', () {
var transform = new FakeDeclaringTransform()
..primaryId = new AssetId('somepackage', 'lib/style.css');
subject.declareOutputs(transform);
expect(transform.outputs.length).toBe(2);
expect(transform.outputs[0].toString())
.toEqual('somepackage|lib/style.css.dart');
expect(transform.outputs[1].toString())
.toEqual('somepackage|lib/style.css.shim.dart');
});
it('should compile stylesheets', () async {
var cssFile = new Asset.fromString(
new AssetId('somepackage', 'lib/style.css'), SIMPLE_CSS);
var transform = new FakeTransform()..primaryInput = cssFile;
await subject.apply(transform);
expect(transform.outputs.length).toBe(2);
expect(transform.outputs[0].id.toString())
.toEqual('somepackage|lib/style.css.dart');
expect(transform.outputs[1].id.toString())
.toEqual('somepackage|lib/style.css.shim.dart');
});
}
@proxy
class FakeTransform implements Transform {
final outputs = <Asset>[];
Asset primaryInput;
addOutput(Asset output) {
this.outputs.add(output);
}
readInputAsString(AssetId id, {Encoding encoding}) {
if (id == primaryInput.id) {
return primaryInput.readAsString(encoding: encoding);
}
throw 'Could not read input $id';
}
noSuchMethod(Invocation i) {
throw '${i.memberName} not implemented';
}
}
@proxy
class FakeDeclaringTransform implements DeclaringTransform {
final outputs = <AssetId>[];
AssetId primaryId;
declareOutput(AssetId output) {
this.outputs.add(output);
}
noSuchMethod(Invocation i) {
throw '${i.memberName} not implemented';
}
}