Index: lib/src/compiler.dart |
diff --git a/lib/src/compiler.dart b/lib/src/compiler.dart |
index 44f7b0d612d54c653461500553b2bbeba47614a3..b325a1d579a1aa4e2e258ebb11eb1cb588259300 100644 |
--- a/lib/src/compiler.dart |
+++ b/lib/src/compiler.dart |
@@ -163,6 +163,14 @@ class Compiler { |
} |
} |
+ // Load stylesheet files referenced by [file]. |
+ for (var href in fileInfo.styleSheetHref) { |
+ if (!_processed.contains(href)) { |
+ _processed.add(href); |
+ _tasks.add(_parseStyleSheetFile(href).then(_processStyleSheetFile)); |
+ } |
+ } |
+ |
// Load .dart files being referenced in the page. |
var src = fileInfo.externalFile; |
if (src != null && !_processed.contains(src)) { |
@@ -196,7 +204,8 @@ class Compiler { |
/** Parse [filename] and treat it as a .dart file. */ |
Future<SourceFile> _parseDartFile(Path path) { |
return fileSystem.readText(path) |
- .then((code) => new SourceFile(path, isDart: true)..code = code) |
+ .then((code) => new SourceFile(path, type: SourceFile.DART) |
+ ..code = code) |
.catchError((e) => _readError(e, path)); |
} |
@@ -237,6 +246,31 @@ class Compiler { |
} |
} |
+ /** Parse [filename] and treat it as a .dart file. */ |
+ Future<SourceFile> _parseStyleSheetFile(Path path) { |
+ return fileSystem.readText(path) |
+ .then((code) => |
+ new SourceFile(path, type: SourceFile.STYLESHEET)..code = code) |
+ .catchError((e) => _readError(e, path)); |
+ } |
+ |
+ void _processStyleSheetFile(SourceFile cssFile) { |
+ if (!_shouldProcessFile(cssFile)) return; |
+ |
+ files.add(cssFile); |
+ |
+ var fileInfo = new FileInfo(cssFile.path); |
+ info[cssFile.path] = fileInfo; |
+ |
+ var uriVisitor = new UriVisitor(_pathInfo, _mainPath, fileInfo.path, |
+ options.rewriteUrls); |
+ var styleSheet = _parseCss(cssFile.path.toString(), |
+ cssFile.code, uriVisitor, options); |
+ if (styleSheet != null) { |
+ fileInfo.styleSheets.add(styleSheet); |
+ } |
+ } |
+ |
Path _getDirectivePath(LibraryInfo libInfo, Directive directive) { |
var uriDirective = (directive as UriBasedDirective).uri; |
var uri = uriDirective.value; |
@@ -417,20 +451,26 @@ class Compiler { |
void _analyze() { |
var uniqueIds = new IntIterator(); |
for (var file in files) { |
- if (file.isDart) continue; |
- _time('Analyzed contents', file.path, () => |
- analyzeFile(file, info, uniqueIds, _messages)); |
+ if (file.isHtml) { |
+ _time('Analyzed contents', file.path, () => |
+ analyzeFile(file, info, uniqueIds, _messages)); |
+ } |
} |
} |
/** Emit the generated code corresponding to each input file. */ |
void _emit() { |
for (var file in files) { |
- if (file.isDart) continue; |
+ if (file.isDart || file.isStyleSheet) continue; |
_time('Codegen', file.path, () { |
var fileInfo = info[file.path]; |
cleanHtmlNodes(fileInfo); |
- _processStylesheet(fileInfo, options: options); |
+ if (!fileInfo.isEntryPoint) { |
+ // Check all components files for <style> tags and parse the CSS. |
+ var uriVisitor = new UriVisitor(_pathInfo, _mainPath, fileInfo.path, |
+ options.rewriteUrls); |
+ _processStylesheet(uriVisitor, fileInfo, options: options); |
+ } |
fixupHtmlCss(fileInfo, options); |
_emitComponents(fileInfo); |
if (fileInfo.isEntryPoint) { |
@@ -439,12 +479,16 @@ class Compiler { |
} |
}); |
} |
+ |
+ if (options.processCss) { |
+ _emitAllCss(); |
+ } |
} |
/** Emit the main .dart file. */ |
void _emitMainDart(SourceFile file) { |
var fileInfo = info[file.path]; |
- var printer = new MainPageEmitter(fileInfo) |
+ var printer = new MainPageEmitter(fileInfo, options.processCss) |
.run(file.document, _pathInfo, _edits[fileInfo.userCode], |
options.rewriteUrls); |
_emitFileAndSourceMaps(fileInfo, printer, fileInfo.inputPath); |
@@ -496,9 +540,64 @@ class Compiler { |
document.outerHtml, source: file.path)); |
} |
+ /** Generate an CSS file for all style sheets (main and components). */ |
+ void _emitAllCss() { |
+ var allCssBuff = new StringBuffer(); |
+ var mainFile; |
+ |
+ // Emit all linked style sheet files first. |
+ for (var file in files) { |
+ var fileInfo = info[file.path]; |
+ if (fileInfo.isEntryPoint) mainFile = file; |
+ if (file.isStyleSheet) { |
+ for (var styleSheet in fileInfo.styleSheets) { |
+ allCssBuff.write( |
+ '/* ==================================================== */\n' |
+ '/* Linked style sheet href = ${file.path.filename} */\n' |
+ '/* ==================================================== */\n'); |
+ allCssBuff.write(emitStyleSheet(styleSheet)); |
+ allCssBuff.write('\n\n'); |
+ } |
+ } |
+ } |
+ |
+ // Emit all CSS in each component (style scoped). |
+ for (var file in files) { |
+ if (file.isHtml) { |
+ var fileInfo = info[file.path]; |
+ for (var component in fileInfo.declaredComponents) { |
+ for (var styleSheet in component.styleSheets) { |
+ allCssBuff.write( |
+ '/* ==================================================== */\n' |
+ '/* Component ${component.tagName} stylesheet */\n' |
+ '/* ==================================================== */\n'); |
+ allCssBuff.write(emitStyleSheet(styleSheet, component.tagName)); |
+ allCssBuff.write('\n\n'); |
+ } |
+ } |
+ } |
+ } |
+ |
+// assert(mainFile != null); |
Siggi Cherem (dart-lang)
2013/03/11 21:13:11
remove commented code?
|
+ |
+ var allCss = allCssBuff.toString(); |
+ if (!allCss.isEmpty) { |
+ var allCssFile = '${mainFile.path.filename}.css'; |
+ var allCssPath = mainFile.path.directoryPath.append(allCssFile); |
+ var allCssOutPath = _pathInfo.outputPath(allCssPath, ''); |
+ output.add(new OutputFile(allCssOutPath, allCss)); |
+ } |
+ } |
+ |
/** Emits the Dart code for all components in [fileInfo]. */ |
void _emitComponents(FileInfo fileInfo) { |
for (var component in fileInfo.declaredComponents) { |
+ // TODO(terry): Handle one stylesheet per component see fixupHtmlCss. |
+ if (component.styleSheets.length > 1 && options.processCss) { |
+ _messages.warning( |
+ 'Component has more than one stylesheet' |
+ ' - first stylesheet used.', null, file: component.externalFile); |
+ } |
var printer = new WebComponentEmitter(fileInfo, _messages) |
.run(component, _pathInfo, _edits[component.userCode]); |
_emitFileAndSourceMaps(component, printer, component.externalFile); |
@@ -568,33 +667,57 @@ class Compiler { |
} |
/** Parse all stylesheet for polyfilling assciated with [info]. */ |
-void _processStylesheet(info, {CompilerOptions options : null}) { |
- new _ProcessCss(options).visit(info); |
+void _processStylesheet(uriVisitor, info, {CompilerOptions options : null}) { |
+ new _ProcessCss(uriVisitor, options).visit(info); |
+} |
+ |
+StyleSheet _parseCss(String src, String content, UriVisitor uriVisitor, |
+ CompilerOptions options) { |
+ if (!content.trim().isEmpty) { |
+ // TODO(terry): Add --checked when fully implemented and error handling. |
+ var styleSheet = css.parse(content, options: |
+ [options.warningsAsErrors ? '--warnings_as_errors' : '', 'memory']); |
+ uriVisitor.visitTree(styleSheet); |
+ if (options.debugCss) { |
+ print('\nCSS source: $src'); |
+ print('==========\n'); |
+ print(treeToDebugString(styleSheet)); |
+ } |
+ return styleSheet; |
+ } |
} |
/** Post-analysis of style sheet; parsed ready for emitting with polyfill. */ |
class _ProcessCss extends InfoVisitor { |
+ final UriVisitor uriVisitor; |
final CompilerOptions options; |
+ ComponentInfo component; |
- _ProcessCss(this.options); |
- |
- // TODO(terry): Add --checked when fully implemented and error handling too. |
- StyleSheet _parseCss(String cssInput, CompilerOptions option) => |
- css.parse(cssInput, options: |
- [option.warningsAsErrors ? '--warnings_as_errors' : '', 'memory']); |
+ _ProcessCss(this.uriVisitor, this.options); |
void visitComponentInfo(ComponentInfo info) { |
- if (!info.cssSource.isEmpty) { |
- info.styleSheet = _parseCss(info.cssSource.toString(), options); |
- info.cssSource = null; // Once CSS parsed original not needed. |
- |
- if (options.debugCss) { |
- print('\nComponent: ${info.tagName}'); |
- print('==========\n'); |
- print(treeToDebugString(info.styleSheet)); |
+ var oldComponent = component; |
+ component = info; |
+ |
+ super.visitComponentInfo(info); |
+ |
+ component = oldComponent; |
+ } |
+ |
+ void visitElementInfo(ElementInfo info) { |
+ if (component != null) { |
+ var node = info.node; |
+ if (node.tagName == 'style' && node.attributes.containsKey("scoped")) { |
+ // Get contents of style tag. |
+ var content = node.nodes.single.value; |
+ var styleSheet = _parseCss(component.tagName, content, uriVisitor, |
+ options); |
+ if (styleSheet != null) { |
+ component.styleSheets.add(styleSheet); |
+ } |
} |
} |
- super.visitComponentInfo(info); |
+ super.visitElementInfo(info); |
} |
} |