OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /** Collects several code emitters for the template tool. */ | 5 /** Collects several code emitters for the template tool. */ |
6 library emitters; | 6 library emitters; |
7 | 7 |
8 import 'package:csslib/parser.dart' as css; | 8 import 'package:csslib/parser.dart' as css; |
9 import 'package:csslib/visitor.dart'; | 9 import 'package:csslib/visitor.dart'; |
10 import 'package:html5lib/dom.dart'; | 10 import 'package:html5lib/dom.dart'; |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 _context.printer.addLine('if (_root is autogenerated.ShadowRoot) ' | 408 _context.printer.addLine('if (_root is autogenerated.ShadowRoot) ' |
409 '_root.applyAuthorStyles = true;'); | 409 '_root.applyAuthorStyles = true;'); |
410 // TODO(jmesserly): warn at runtime if apply-author-styles was not set, | 410 // TODO(jmesserly): warn at runtime if apply-author-styles was not set, |
411 // and we don't have Shadow DOM support? In that case, styles won't have | 411 // and we don't have Shadow DOM support? In that case, styles won't have |
412 // proper encapsulation. | 412 // proper encapsulation. |
413 } | 413 } |
414 | 414 |
415 if (info.template != null && !elemInfo.childrenCreatedInCode) { | 415 if (info.template != null && !elemInfo.childrenCreatedInCode) { |
416 // TODO(jmesserly): scoped styles probably don't work when | 416 // TODO(jmesserly): scoped styles probably don't work when |
417 // childrenCreatedInCode is true. | 417 // childrenCreatedInCode is true. |
418 if (info.styleSheet != null) { | 418 if (!info.styleSheets.isEmpty && !cssPolyfill) { |
419 var tag = cssPolyfill ? info.tagName : null; | |
420 // TODO(jmesserly): csslib+html5lib should work together. We shouldn't | 419 // TODO(jmesserly): csslib+html5lib should work together. We shouldn't |
421 // need to call a different function to serialize CSS. | 420 // need to call a different function to serialize CSS. |
422 // Calling innerHTML on a StyleElement should be | 421 // Calling innerHTML on a StyleElement should be |
423 // enought - like a real browser. CSSOM and DOM | 422 // enought - like a real browser. CSSOM and DOM |
424 // should work together in the same tree. | 423 // should work together in the same tree. |
425 // TODO(terry): Consider not emitting <style> tag inside of component. | 424 // TODO(terry): Only one style tag per component. |
426 // Maybe we can generate a .css file that has all the CSS | |
427 // polyfill. The style tag can change the rendering a bit. | |
428 var styleSheet = | 425 var styleSheet = |
429 '<style>\n' | 426 '<style scoped>\n' |
430 '${emitStyleSheet(info.styleSheet, tag)}' | 427 '${emitStyleSheet(info.styleSheets[0])}' |
431 '\n</style>'; | 428 '\n</style>'; |
432 var template = elemInfo.node; | 429 var template = elemInfo.node; |
433 template.insertBefore(new Element.html(styleSheet), | 430 template.insertBefore(new Element.html(styleSheet), |
434 template.children[0]); | 431 template.children[0]); |
435 } | 432 } |
436 | 433 |
437 _context.statics.add('final', '__shadowTemplate', | 434 _context.statics.add('final', '__shadowTemplate', |
438 elemInfo.node.sourceSpan, | 435 elemInfo.node.sourceSpan, |
439 "new autogenerated.DocumentFragment.html('''" | 436 "new autogenerated.DocumentFragment.html('''" |
440 "${escapeDartString(elemInfo.node.innerHtml, triple: true)}" | 437 "${escapeDartString(elemInfo.node.innerHtml, triple: true)}" |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 var pos = classDecl.leftBracket.end; | 512 var pos = classDecl.leftBracket.end; |
516 transaction.edit(pos, pos, classBody); | 513 transaction.edit(pos, pos, classBody); |
517 | 514 |
518 // Emit all the code in a single printer, keeping track of source-maps. | 515 // Emit all the code in a single printer, keeping track of source-maps. |
519 return transaction.commit(); | 516 return transaction.commit(); |
520 } | 517 } |
521 } | 518 } |
522 | 519 |
523 /** Generates the class corresponding to the main html page. */ | 520 /** Generates the class corresponding to the main html page. */ |
524 class MainPageEmitter extends RecursiveEmitter { | 521 class MainPageEmitter extends RecursiveEmitter { |
525 MainPageEmitter(FileInfo fileInfo) : super(fileInfo, new Context(indent: 1)); | 522 final bool _cssPolyfill; |
| 523 |
| 524 MainPageEmitter(FileInfo fileInfo, [bool cssPolyfill = false]) : |
| 525 this._cssPolyfill = cssPolyfill, super(fileInfo, new Context(indent: 1)); |
526 | 526 |
527 CodePrinter run(Document document, PathInfo pathInfo, | 527 CodePrinter run(Document document, PathInfo pathInfo, |
528 TextEditTransaction transaction, bool rewriteUrls) { | 528 TextEditTransaction transaction, bool rewriteUrls) { |
529 visit(_fileInfo.bodyInfo); | 529 visit(_fileInfo.bodyInfo); |
530 | 530 |
531 // fix up the URLs to content that is not modified by the compiler | 531 // fix up the URLs to content that is not modified by the compiler |
532 document.queryAll('script').forEach((tag) { | 532 document.queryAll('script').forEach((tag) { |
533 var src = tag.attributes["src"]; | 533 var src = tag.attributes["src"]; |
534 if (tag.attributes['type'] == 'application/dart') { | 534 if (tag.attributes['type'] == 'application/dart') { |
535 tag.remove(); | 535 tag.remove(); |
536 } else if (src != null && rewriteUrls) { | 536 } else if (src != null && rewriteUrls) { |
537 tag.attributes["src"] = pathInfo.transformUrl(_fileInfo.path, src); | 537 tag.attributes["src"] = pathInfo.transformUrl(_fileInfo.path, src); |
538 } | 538 } |
539 }); | 539 }); |
540 document.queryAll('link').forEach((tag) { | 540 document.queryAll('link').forEach((tag) { |
541 var href = tag.attributes['href']; | 541 var href = tag.attributes['href']; |
542 if (tag.attributes['rel'] == 'components') { | 542 var rel = tag.attributes['rel']; |
| 543 if (rel == 'component' || rel == 'components') { |
543 tag.remove(); | 544 tag.remove(); |
| 545 } else if (_cssPolyfill && |
| 546 rel == 'stylesheet' && !href.startsWith('http')) { |
| 547 tag.remove(); |
544 } else if (href != null && rewriteUrls) { | 548 } else if (href != null && rewriteUrls) { |
545 tag.attributes['href'] = pathInfo.transformUrl(_fileInfo.path, href); | 549 tag.attributes['href'] = pathInfo.transformUrl(_fileInfo.path, href); |
546 } | 550 } |
547 }); | 551 }); |
548 | 552 |
| 553 if (_cssPolyfill) { |
| 554 var linkElem = new Element.html('<link rel="stylesheet" type="text/css"' |
| 555 ' href="${_fileInfo.path.filename}.css">'); |
| 556 var head = document.head; |
| 557 head.insertBefore(linkElem, |
| 558 head.hasChildNodes() ? head.nodes.first : null); |
| 559 } |
549 | 560 |
550 var codeInfo = _fileInfo.userCode; | 561 var codeInfo = _fileInfo.userCode; |
551 if (codeInfo == null) { | 562 if (codeInfo == null) { |
552 assert(transaction == null); | 563 assert(transaction == null); |
553 codeInfo = new DartCodeInfo(null, null, [], 'main(){\n}', null); | 564 codeInfo = new DartCodeInfo(null, null, [], 'main(){\n}', null); |
554 } | 565 } |
555 | 566 |
556 if (transaction == null) { | 567 if (transaction == null) { |
557 transaction = new TextEditTransaction(codeInfo.code, codeInfo.sourceFile); | 568 transaction = new TextEditTransaction(codeInfo.code, codeInfo.sourceFile); |
558 } | 569 } |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
679 } | 690 } |
680 typeName = htmlElementExtends[typeName]; | 691 typeName = htmlElementExtends[typeName]; |
681 } | 692 } |
682 // If we didn't find a DOM setter, and this is a component, set a property on | 693 // If we didn't find a DOM setter, and this is a component, set a property on |
683 // the component. | 694 // the component. |
684 if (info.component != null && !name.startsWith('data-')) { | 695 if (info.component != null && !name.startsWith('data-')) { |
685 return 'xtag.${toCamelCase(name)}'; | 696 return 'xtag.${toCamelCase(name)}'; |
686 } | 697 } |
687 return "attributes['$name']"; | 698 return "attributes['$name']"; |
688 } | 699 } |
OLD | NEW |