Index: lib/src/emitters.dart |
diff --git a/lib/src/emitters.dart b/lib/src/emitters.dart |
index a7de9c2d0c21eb91c52b10352db7887769f17f16..34d0d8686780a4d2537c7f7e9ba5c4c940c6866e 100644 |
--- a/lib/src/emitters.dart |
+++ b/lib/src/emitters.dart |
@@ -12,35 +12,18 @@ import 'package:html5lib/dom_parsing.dart'; |
import 'package:html5lib/parser.dart'; |
import 'package:source_maps/span.dart' show Span, FileLocation; |
-import 'compiler.dart'; |
import 'code_printer.dart'; |
+import 'compiler.dart'; |
import 'dart_parser.dart' show DartCodeInfo; |
-import 'html_css_fixup.dart'; |
import 'html5_utils.dart'; |
+import 'html_css_fixup.dart'; |
import 'info.dart'; |
import 'messages.dart'; |
+import 'options.dart'; |
import 'paths.dart'; |
import 'refactor.dart'; |
import 'utils.dart'; |
-/** |
- * Context used by an emitter. Typically representing where to generate code |
- * and additional information, such as total number of generated identifiers. |
- */ |
-class Context { |
- final Declarations statics; |
- final CodePrinter printer; |
- final bool isClass; |
- |
- Context({Declarations statics, CodePrinter printer, bool isClass: false, |
- int indent: 0}) |
- : this.statics = statics != null |
- ? statics : new Declarations(indent, staticKeyword: isClass), |
- this.isClass = isClass, |
- this.printer = printer != null |
- ? printer : new CodePrinter(isClass ? indent + 1 : indent); |
-} |
- |
/** Only x-tag name element selectors are emitted as [is="x-"]. */ |
class CssEmitter extends CssPrinter { |
@@ -199,33 +182,15 @@ class WebComponentEmitter { |
final Messages messages; |
final FileInfo _fileInfo; |
final CssPolyfillKind cssPolyfillKind; |
- Context _context; |
- WebComponentEmitter(this._fileInfo, this.messages, this.cssPolyfillKind) |
- : _context = new Context(isClass: true, indent: 1); |
+ WebComponentEmitter(this._fileInfo, this.messages, this.cssPolyfillKind); |
CodePrinter run(ComponentInfo info, PathMapper pathMapper, |
TextEditTransaction transaction) { |
- var templateNode = info.elementNode; |
- |
- // elementNode is pointing at template tag (no attributes). |
- assert(templateNode.tagName == 'element'); |
- for (var node in templateNode.nodes) { |
- if (node.tagName == 'template') { |
- templateNode = node; |
- break; |
- } |
- } |
+ var templateNode = info.element.nodes.firstWhere( |
+ (n) => n.tagName == 'template', orElse: () => null); |
- if (info.element.attributes['apply-author-styles'] != null) { |
- _context.printer.addLine('if (__root is autogenerated.ShadowRoot) ' |
- '__root.applyAuthorStyles = true;'); |
- // TODO(jmesserly): warn at runtime if apply-author-styles was not set, |
- // and we don't have Shadow DOM support? In that case, styles won't have |
- // proper encapsulation. |
- } |
- |
- if (templateNode.tagName == 'template') { |
+ if (templateNode != null) { |
if (!info.styleSheets.isEmpty && !messages.options.processCss) { |
// TODO(terry): Only one style tag per component. |
@@ -240,24 +205,6 @@ class WebComponentEmitter { |
new Element.html('<style>\n$styleText\n</style>'), |
templateNode.hasChildNodes() ? templateNode.children[0] : null); |
} |
- |
- _context.statics.add('final', '__shadowTemplate', |
- templateNode.sourceSpan, |
- "new autogenerated.DocumentFragment.html('''" |
- "${escapeDartString(templateNode.innerHtml, triple: true)}" |
- "''')"); |
- |
- var syntax = templateNode.attributes['syntax']; |
- if (syntax != null) { |
- syntax = escapeDartString(syntax); |
- syntax = ", autogenerated.TemplateElement.syntax['$syntax']"; |
- } else { |
- syntax = ""; |
- } |
- |
- _context.printer |
- ..addLine("__root.nodes.add(cloneTemplate(__shadowTemplate));") |
- ..addLine("autogenerated_mdv.bindModel(__root, this$syntax);"); |
} |
bool hasExtends = info.extendsComponent != null; |
@@ -281,30 +228,8 @@ class WebComponentEmitter { |
header.addLine(''); |
transaction.edit(0, codeInfo.directivesEnd, header); |
- var mangle = cssPolyfillKind == CssPolyfillKind.MANGLED_POLYFILL; |
- var cssMapExpression = createCssSelectorsExpression(info, mangle); |
var classBody = new CodePrinter(1) |
..add('\n') |
- ..addLine('/** Autogenerated from the template. */') |
- ..addLine('') |
- // TODO(terry): Remove [_css]; after migrating to getScopedCss. |
- ..addLine('autogenerated.ScopedCssMapper _css;') |
- ..addLine('') |
- ..addLine('/** This field is deprecated, use getShadowRoot instead. */') |
- ..addLine('get _root => getShadowRoot("${info.tagName}");') |
- ..add(_context.statics) |
- ..addLine('') |
- ..addLine('void initShadow() {') |
- ..addLine(hasExtends ? ' super.initShadow();' : null) |
- ..addLine(' var __root = createShadowRoot("${info.tagName}");') |
- ..addLine(' shadowRootReady(__root, "${info.tagName}");') |
- ..addLine(' setScopedCss("${info.tagName}", ' |
- 'new autogenerated.ScopedCssMapper($cssMapExpression));') |
- // TODO(terry): Remove assignment after migrating to getScopedCss. |
- ..addLine(' _css = getScopedCss("${info.tagName}");') |
- ..add(_context.printer) |
- ..addLine('}') |
- ..addLine('') |
..addLine('/** Original code from the component. */'); |
var pos = classDecl.leftBracket.end; |
@@ -315,63 +240,50 @@ class WebComponentEmitter { |
} |
} |
-/** Generates the class corresponding to the main html page. */ |
-class EntryPointEmitter { |
- final GlobalInfo global; |
- final FileInfo _fileInfo; |
- Context _context; |
- |
- EntryPointEmitter(this._fileInfo, this.global) |
- : _context = new Context(indent: 1); |
+/** The code that will be used to bootstrap the application. */ |
+CodePrinter generateBootstrapCode( |
+ FileInfo info, FileInfo userMainInfo, GlobalInfo global, |
+ PathMapper pathMapper, CompilerOptions options) { |
- CodePrinter run(PathMapper pathMapper, TextEditTransaction transaction, |
- bool rewriteUrls) { |
+ var printer = new CodePrinter(0) |
+ ..addLine('library app_bootstrap;') |
+ ..addLine('') |
+ ..addLine("import 'package:polymer/polymer.dart' as polymer;"); |
- var filePath = _fileInfo.inputUrl.resolvedPath; |
- |
- var codeInfo = _fileInfo.userCode; |
- if (codeInfo == null) { |
- assert(transaction == null); |
- codeInfo = new DartCodeInfo(null, null, [], 'main(){\n}', null); |
- } |
- |
- if (transaction == null) { |
- transaction = new TextEditTransaction(codeInfo.code, codeInfo.sourceFile); |
- } |
+ if (userMainInfo.userCode != null) { |
+ printer..addLine('') |
+ ..addLine("import '${pathMapper.importUrlFor(info, userMainInfo)}' " |
+ "as userMain;\n"); |
+ } |
- var libraryName = codeInfo.libraryName != null |
- ? codeInfo.libraryName : _fileInfo.libraryName; |
- var header = new CodePrinter(0); |
- header.add(_header(path.basename(filePath), libraryName)); |
- emitImports(codeInfo, _fileInfo, pathMapper, header, global); |
- header..addLine('') |
- ..addLine('') |
- ..addLine('// Original code'); |
- transaction.edit(0, codeInfo.directivesEnd, header); |
+ for (var c in global.components.values) { |
+ if (c.hasConflict) continue; |
+ printer.addLine("import '${pathMapper.importUrlFor(info, c)}';"); |
+ } |
- var printer = (transaction.commit()) |
- ..addLine('') |
- ..addLine('// Additional generated code') |
- ..addLine('void init_autogenerated() {') |
- ..indent += 1; |
+ printer..addLine('') |
+ ..addLine('void main() {') |
+ ..indent += 1; |
+ |
+ if (userMainInfo.userCode != null) printer.addLine('userMain.main();'); |
+ |
+ for (var c in global.components.values) { |
+ if (c.hasConflict) continue; |
+ var tagName = escapeDartString(c.tagName); |
+ var cssMapExpression = createCssSelectorsExpression(c, |
+ CssPolyfillKind.of(options, c)); |
+ printer |
+ ..addLine("polymer.setScopedCss('$tagName', $cssMapExpression);") |
+ ..addLine("polymer.registerPolymerElement(" |
+ "'$tagName', () => new ${c.className}());"); |
+ } |
- for (var c in global.components.values) { |
- if (c.hasConflict) continue; |
- var tagName = escapeDartString(c.tagName); |
+ return printer |
+ ..indent -= 1 |
+ ..addLine('}'); |
+} |
- printer.addLine("autogenerated.registerPolymerElement(" |
- "new autogenerated.Element.html(" |
- "'${escapeDartString(c.elementNode.outerHtml)}')" |
- ", () => new ${c.className}());"); |
- } |
- return printer |
- ..add(_context.statics) |
- ..add(_context.printer) |
- ..indent -= 1 |
- ..addLine('}'); |
- } |
-} |
/** |
* List of HTML4 elements which could have relative URL resource: |
@@ -451,7 +363,8 @@ final shadowDomJS = new RegExp(r'shadowdom\..*\.js', caseSensitive: false); |
/** Trim down the html for the main html page. */ |
void transformMainHtml(Document document, FileInfo fileInfo, |
- PathMapper pathMapper, bool hasCss, bool rewriteUrls, Messages messages) { |
+ PathMapper pathMapper, bool hasCss, bool rewriteUrls, |
+ Messages messages, GlobalInfo global) { |
var filePath = fileInfo.inputUrl.resolvedPath; |
bool dartLoaderFound = false; |
@@ -472,6 +385,7 @@ void transformMainHtml(Document document, FileInfo fileInfo, |
tag.attributes["src"] = pathMapper.transformUrl(filePath, src); |
} |
} |
+ |
for (var tag in document.queryAll('link')) { |
var href = tag.attributes['href']; |
var rel = tag.attributes['rel']; |
@@ -512,6 +426,21 @@ void transformMainHtml(Document document, FileInfo fileInfo, |
document.head.nodes.insert(0, parseFragment( |
'<style>template { display: none; }</style>')); |
+ // Move all <element> declarations to the main HTML file |
+ // TODO(sigmund): remove this once we have HTMLImports implemented. |
+ for (var c in global.components.values) { |
+ document.body.nodes.insert(0, new Text('\n')); |
+ var fragment = c.element; |
+ for (var tag in fragment.queryAll('script')) { |
+ // TODO(sigmund): leave script tags around when we start using "boot.js" |
+ if (tag.attributes['type'] == 'application/dart') { |
+ tag.remove(); |
+ } |
+ } |
+ document.body.nodes.insert(0, fragment); |
+ } |
+ |
+ |
if (!shadowDomFound) { |
// TODO(jmesserly): we probably shouldn't add this automatically. |
document.body.nodes.add(parseFragment('<script type="text/javascript" ' |
@@ -522,6 +451,7 @@ void transformMainHtml(Document document, FileInfo fileInfo, |
//messages.warning('Missing script to load Dart. ' |
// 'Please add this line to your HTML file: $dartLoader', |
// document.body.sourceSpan); |
+ // TODO(sigmund): switch to 'boot.js' |
document.body.nodes.add(parseFragment('<script type="text/javascript" ' |
'src="packages/browser/dart.js"></script>\n')); |
} |