| 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'));
|
| }
|
|
|