Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: lib/src/emitters.dart

Issue 22962005: Merge pull request #581 from kevmoo/polymer (Closed) Base URL: https://github.com/dart-lang/web-ui.git@polymer
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/src/dart_parser.dart ('k') | lib/src/files.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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;
9 import 'package:csslib/visitor.dart';
10 import 'package:html5lib/dom.dart'; 8 import 'package:html5lib/dom.dart';
11 import 'package:html5lib/dom_parsing.dart'; 9 import 'package:html5lib/dom_parsing.dart' show TreeVisitor;
12 import 'package:html5lib/parser.dart'; 10 import 'package:html5lib/parser.dart' show parseFragment;
13 import 'package:source_maps/span.dart' show Span, FileLocation; 11 import 'package:source_maps/printer.dart';
12 import 'package:source_maps/refactor.dart';
14 13
15 import 'code_printer.dart'; 14 import 'compiler_options.dart';
16 import 'compiler.dart'; 15 import 'css_emitters.dart' show emitStyleSheet, emitOriginalCss;
17 import 'dart_parser.dart' show DartCodeInfo;
18 import 'html5_utils.dart'; 16 import 'html5_utils.dart';
19 import 'html_css_fixup.dart'; 17 import 'info.dart' show ComponentInfo, FileInfo, GlobalInfo;
20 import 'info.dart';
21 import 'messages.dart'; 18 import 'messages.dart';
22 import 'compiler_options.dart'; 19 import 'paths.dart' show PathMapper;
23 import 'paths.dart'; 20 import 'utils.dart' show escapeDartString, path;
24 import 'refactor.dart';
25 import 'utils.dart';
26
27
28 /** Only x-tag name element selectors are emitted as [is="x-"]. */
29 class CssEmitter extends CssPrinter {
30 final Set _componentsTag;
31
32 CssEmitter(this._componentsTag);
33
34 /**
35 * If element selector is a component's tag name, then change selector to
36 * find element who's is attribute's the component's name.
37 */
38 bool _emitComponentElement(ElementSelector node) {
39 if (_componentsTag.contains(node.name)) {
40 emit('[is="${node.name}"]');
41 return true;
42 }
43 return false;
44 }
45
46 void visitElementSelector(ElementSelector node) {
47 if (_componentsTag.isNotEmpty && _emitComponentElement(node)) return;
48 super.visitElementSelector(node);
49 }
50
51 }
52
53 /**
54 * Style sheet polyfill for a component, each CSS class name/id selector
55 * referenced (selector) is prepended with prefix_ (if prefix is non-null). In
56 * addition an element selector this is a component's tag name is transformed
57 * to the attribute selector [is="x-"] where x- is the component's tag name.
58 */
59 class ComponentCssEmitter extends CssPrinter {
60 final String _componentTagName;
61 final CssPolyfillKind _polyfillKind;
62 bool _inHostDirective = false;
63 bool _selectorStartInHostDirective = false;
64
65 ComponentCssEmitter(this._componentTagName, this._polyfillKind);
66
67 /** Is the element selector an x-tag name. */
68 bool _isSelectorElementXTag(Selector node) {
69 if (node.simpleSelectorSequences.length > 0) {
70 var selector = node.simpleSelectorSequences[0].simpleSelector;
71 return selector is ElementSelector && selector.name == _componentTagName;
72 }
73 return false;
74 }
75
76 /**
77 * If element selector is the component's tag name, then change selector to
78 * find element who's is attribute is the component's name.
79 */
80 bool _emitComponentElement(ElementSelector node) {
81 if (_polyfillKind == CssPolyfillKind.SCOPED_POLYFILL &&
82 _componentTagName == node.name) {
83 emit('[is="$_componentTagName"]');
84 return true;
85 }
86 return false;
87 }
88
89 void visitSelector(Selector node) {
90 // If the selector starts with an x-tag name don't emit it twice.
91 if (!_isSelectorElementXTag(node) &&
92 _polyfillKind == CssPolyfillKind.SCOPED_POLYFILL) {
93 if (_inHostDirective) {
94 // Style the element that's hosting the component, therefore don't emit
95 // the descendent combinator (first space after the [is="x-..."]).
96 emit('[is="$_componentTagName"]');
97 // Signal that first simpleSelector must be checked.
98 _selectorStartInHostDirective = true;
99 } else {
100 // Emit its scoped as a descendent (space at end).
101 emit('[is="$_componentTagName"] ');
102 }
103 }
104 super.visitSelector(node);
105 }
106
107 /**
108 * If first simple selector of a ruleset in a @host directive is a wildcard
109 * then don't emit the wildcard.
110 */
111 void visitSimpleSelectorSequence(SimpleSelectorSequence node) {
112 if (_selectorStartInHostDirective) {
113 _selectorStartInHostDirective = false;
114 if (_polyfillKind == CssPolyfillKind.SCOPED_POLYFILL &&
115 node.simpleSelector.isWildcard) {
116 // Skip the wildcard if first item in the sequence.
117 return;
118 }
119 assert(node.isCombinatorNone);
120 }
121
122 super.visitSimpleSelectorSequence(node);
123 }
124
125 void visitClassSelector(ClassSelector node) {
126 if (_polyfillKind == CssPolyfillKind.MANGLED_POLYFILL) {
127 emit('.${_componentTagName}_${node.name}');
128 } else {
129 super.visitClassSelector(node);
130 }
131 }
132
133 void visitIdSelector(IdSelector node) {
134 if (_polyfillKind == CssPolyfillKind.MANGLED_POLYFILL) {
135 emit('#${_componentTagName}_${node.name}');
136 } else {
137 super.visitIdSelector(node);
138 }
139 }
140
141 void visitElementSelector(ElementSelector node) {
142 if (_emitComponentElement(node)) return;
143 super.visitElementSelector(node);
144 }
145
146 /**
147 * If we're polyfilling scoped styles the @host directive is stripped. Any
148 * ruleset(s) processed in an @host will fixup the first selector. See
149 * visitSelector and visitSimpleSelectorSequence in this class, they adjust
150 * the selectors so it styles the element hosting the compopnent.
151 */
152 void visitHostDirective(HostDirective node) {
153 if (_polyfillKind == CssPolyfillKind.SCOPED_POLYFILL) {
154 _inHostDirective = true;
155 emit('/* @host */');
156 for (var ruleset in node.rulesets) {
157 ruleset.visit(this);
158 }
159 _inHostDirective = false;
160 emit('/* end of @host */\n');
161 } else {
162 super.visitHostDirective(node);
163 }
164 }
165 }
166
167 /**
168 * Helper function to emit the contents of the style tag outside of a component.
169 */
170 String emitStyleSheet(StyleSheet ss, FileInfo file) =>
171 (new CssEmitter(file.components.keys.toSet())
172 ..visitTree(ss, pretty: true)).toString();
173
174 /** Helper function to emit a component's style tag content. */
175 String emitComponentStyleSheet(StyleSheet ss, String tagName,
176 CssPolyfillKind polyfillKind) =>
177 (new ComponentCssEmitter(tagName, polyfillKind)
178 ..visitTree(ss, pretty: true)).toString();
179 21
180 /** Generates the class corresponding to a single web component. */ 22 /** Generates the class corresponding to a single web component. */
181 class WebComponentEmitter { 23 NestedPrinter emitPolymerElement(ComponentInfo info, PathMapper pathMapper,
182 final Messages messages; 24 TextEditTransaction transaction, CompilerOptions options) {
183 final FileInfo _fileInfo; 25 if (info.classDeclaration == null) return null;
184 final CssPolyfillKind cssPolyfillKind;
185 26
186 WebComponentEmitter(this._fileInfo, this.messages, this.cssPolyfillKind); 27 var codeInfo = info.userCode;
187 28 if (transaction == null) {
188 CodePrinter run(ComponentInfo info, PathMapper pathMapper, 29 // TODO(sigmund): avoid emitting this file if we don't need to do any
189 TextEditTransaction transaction) { 30 // modifications (e.g. no @observable and not adding the libraryName).
190 var templateNode = info.element.nodes.firstWhere( 31 transaction = new TextEditTransaction(codeInfo.code, codeInfo.sourceFile);
191 (n) => n.tagName == 'template', orElse: () => null);
192
193 if (templateNode != null) {
194 if (!info.styleSheets.isEmpty && !messages.options.processCss) {
195 // TODO(terry): Only one style tag per component.
196
197 // TODO(jmesserly): csslib + html5lib should work together.
198 // We shouldn't need to call a different function to serialize CSS.
199 // Calling innerHtml on a StyleElement should be enought - like a real
200 // browser. CSSOM and DOM should work together in the same tree.
201 var styleText = emitComponentStyleSheet(
202 info.styleSheets[0], info.tagName, cssPolyfillKind);
203
204 templateNode.insertBefore(
205 new Element.html('<style>\n$styleText\n</style>'),
206 templateNode.hasChildNodes() ? templateNode.children[0] : null);
207 }
208 }
209
210 bool hasExtends = info.extendsComponent != null;
211 var codeInfo = info.userCode;
212 var classDecl = info.classDeclaration;
213 if (classDecl == null) return null;
214
215 if (transaction == null) {
216 transaction = new TextEditTransaction(codeInfo.code, codeInfo.sourceFile);
217 }
218
219 // Expand the headers to include polymer imports, unless they are already
220 // present.
221 var libraryName = (codeInfo.libraryName != null)
222 ? codeInfo.libraryName
223 : info.tagName.replaceAll(new RegExp('[-./]'), '_');
224 var header = new CodePrinter(0);
225 header.add(_header(path.basename(info.declaringFile.inputUrl.resolvedPath),
226 libraryName));
227 emitImports(codeInfo, info, pathMapper, header);
228 header.addLine('');
229 transaction.edit(0, codeInfo.directivesEnd, header);
230
231 var classBody = new CodePrinter(1)
232 ..add('\n')
233 ..addLine('/** Original code from the component. */');
234
235 var pos = classDecl.leftBracket.end;
236 transaction.edit(pos, pos, classBody);
237
238 // Emit all the code in a single printer, keeping track of source-maps.
239 return transaction.commit();
240 } 32 }
33 if (codeInfo.libraryName == null) {
34 // For deploy, we need to import the library associated with the component,
35 // so we need to ensure there is a library directive.
36 var libraryName = info.tagName.replaceAll(new RegExp('[-./]'), '_');
37 transaction.edit(0, 0, 'library $libraryName;');
38 }
39 return transaction.commit();
241 } 40 }
242 41
243 /** The code that will be used to bootstrap the application. */ 42 /** The code that will be used to bootstrap the application. */
244 CodePrinter generateBootstrapCode( 43 NestedPrinter generateBootstrapCode(
245 FileInfo info, FileInfo userMainInfo, GlobalInfo global, 44 FileInfo info, FileInfo userMainInfo, GlobalInfo global,
246 PathMapper pathMapper, CompilerOptions options) { 45 PathMapper pathMapper, CompilerOptions options) {
247 46
248 var printer = new CodePrinter(0) 47 var printer = new NestedPrinter(0)
249 ..addLine('library app_bootstrap;') 48 ..addLine('library app_bootstrap;')
250 ..addLine('') 49 ..addLine('')
251 ..addLine("import 'package:polymer/polymer.dart';") 50 ..addLine("import 'package:polymer/polymer.dart';")
252 ..addLine("import 'dart:mirrors' show currentMirrorSystem;"); 51 ..addLine("import 'dart:mirrors' show currentMirrorSystem;");
253
254 if (userMainInfo.userCode != null) { 52 if (userMainInfo.userCode != null) {
255 printer..addLine('') 53 printer..addLine("import '${pathMapper.importUrlFor(info, userMainInfo)}' "
256 ..addLine("import '${pathMapper.importUrlFor(info, userMainInfo)}' " 54 "as userMain;\n");
257 "as userMain;\n");
258 } 55 }
259 56
260 int i = 0; 57 int i = 0;
261 for (var c in global.components.values) { 58 for (var c in global.components.values) {
262 if (c.hasConflict) continue; 59 if (c.hasConflict) continue;
263 printer.addLine("import '${pathMapper.importUrlFor(info, c)}' as i$i;"); 60 printer.addLine("import '${pathMapper.importUrlFor(info, c)}' as i$i;");
264 i++; 61 i++;
265 } 62 }
266 63
267 printer..addLine('') 64 printer..addLine('')
268 ..addLine('void main() {') 65 ..addLine('void main() {')
269 ..indent += 1 66 ..indent += 1
270 ..addLine("initPolymer([") 67 ..addLine("initPolymer([")
271 ..indent += 2; 68 ..indent += 2;
272 69
273 for (var c in global.components.values) { 70 for (var c in global.components.values) {
274 if (c.hasConflict) continue; 71 if (c.hasConflict) continue;
275 var tagName = escapeDartString(c.tagName);
276 var cssMapExpression = createCssSelectorsExpression(c,
277 CssPolyfillKind.of(options, c));
278 printer.addLine("'${pathMapper.importUrlFor(info, c)}',"); 72 printer.addLine("'${pathMapper.importUrlFor(info, c)}',");
279 } 73 }
280 74
281 return printer 75 return printer
282 ..indent -= 1 76 ..indent -= 1
283 ..addLine('],') 77 ..addLine('],')
284 ..addLine(userMainInfo.userCode != null ? 'userMain.main,' : '() {},') 78 ..addLine(userMainInfo.userCode != null ? 'userMain.main,' : '() {},')
285 ..addLine( 79 ..addLine(
286 "currentMirrorSystem().findLibrary(const Symbol('app_bootstrap'))") 80 "currentMirrorSystem().findLibrary(const Symbol('app_bootstrap'))")
287 ..indent += 2 81 ..indent += 2
288 ..addLine(".first.uri.toString());") 82 ..addLine(".first.uri.toString());")
289 ..indent -= 4 83 ..indent -= 4
290 ..addLine('}'); 84 ..addLine('}');
291 } 85 }
292 86
293 87
294
295 /** 88 /**
296 * List of HTML4 elements which could have relative URL resource: 89 * Rewrites attributes that contain relative URL (excluding src urls in script
297 * 90 * and link tags which are already rewritten by other parts of the compiler).
298 * <body background=url>, <img src=url>, <input src=url>
299 *
300 * HTML 5:
301 *
302 * <audio src=url>, <command icon=url>, <embed src=url>,
303 * <source src=url>, <video poster=url> and <video src=url>
304 */ 91 */
305 class AttributeUrlTransform extends TreeVisitor { 92 class _AttributeUrlTransform extends TreeVisitor {
306 final String filePath; 93 final String filePath;
307 final PathMapper pathMapper; 94 final PathMapper pathMapper;
308 95
309 AttributeUrlTransform(this.filePath, this.pathMapper); 96 _AttributeUrlTransform(this.filePath, this.pathMapper);
310 97
311 visitElement(Element node) { 98 visitElement(Element node) {
312 if (node.tagName == 'script') return; 99 if (node.tagName == 'script') return;
313 if (node.tagName == 'link') return; 100 if (node.tagName == 'link') return;
314 101
315 for (var key in node.attributes.keys) { 102 for (var key in node.attributes.keys) {
316 if (urlAttributes.contains(key)) { 103 if (urlAttributes.contains(key)) {
317 // Rewrite the URL attribute. 104 node.attributes[key] =
318 node.attributes[key] = pathMapper.transformUrl(filePath, 105 pathMapper.transformUrl(filePath, node.attributes[key]);
319 node.attributes[key]);
320 } 106 }
321 } 107 }
322
323 super.visitElement(node); 108 super.visitElement(node);
324 } 109 }
325 } 110 }
326 111
327 void _transformRelativeUrlAttributes(Document document, PathMapper pathMapper, 112 final _shadowDomJS = new RegExp(r'shadowdom\..*\.js', caseSensitive: false);
328 String filePath) { 113 final _bootJS = new RegExp(r'.*/polymer/boot.js', caseSensitive: false);
329 // Transform any element's attribute which is a relative URL.
330 new AttributeUrlTransform(filePath, pathMapper).visit(document);
331 }
332
333 void emitImports(DartCodeInfo codeInfo, LibraryInfo info, PathMapper pathMapper,
334 CodePrinter printer, [GlobalInfo global]) {
335 var seenImports = new Set();
336 addUnique(String importString, [location]) {
337 if (!seenImports.contains(importString)) {
338 printer.addLine(importString, location: location);
339 seenImports.add(importString);
340 }
341 }
342
343 // Add imports only for those components used by this component.
344 for (var c in info.usedComponents.keys) {
345 addUnique("import '${pathMapper.importUrlFor(info, c)}';");
346 }
347
348 if (global != null) {
349 for (var c in global.components.values) {
350 addUnique("import '${pathMapper.importUrlFor(info, c)}';");
351 }
352 }
353
354 if (info is ComponentInfo) {
355 // Inject an import to the base component.
356 var base = (info as ComponentInfo).extendsComponent;
357 if (base != null) {
358 addUnique("import '${pathMapper.importUrlFor(info, base)}';");
359 }
360 }
361
362 // Add existing import, export, and part directives.
363 var file = codeInfo.sourceFile;
364 for (var d in codeInfo.directives) {
365 addUnique(d.toString(), file != null ? file.location(d.offset) : null);
366 }
367 }
368
369 final shadowDomJS = new RegExp(r'shadowdom\..*\.js', caseSensitive: false);
370 final bootJS = new RegExp(r'.*/polymer/boot.js', caseSensitive: false);
371 114
372 /** Trim down the html for the main html page. */ 115 /** Trim down the html for the main html page. */
373 void transformMainHtml(Document document, FileInfo fileInfo, 116 void transformMainHtml(Document document, FileInfo fileInfo,
374 PathMapper pathMapper, bool hasCss, bool rewriteUrls, 117 PathMapper pathMapper, bool hasCss, bool rewriteUrls,
375 Messages messages, GlobalInfo global) { 118 Messages messages, GlobalInfo global) {
376 var filePath = fileInfo.inputUrl.resolvedPath; 119 var filePath = fileInfo.inputUrl.resolvedPath;
377 120
378 bool dartLoaderFound = false; 121 bool dartLoaderFound = false;
379 bool shadowDomFound = false; 122 bool shadowDomFound = false;
380 for (var tag in document.queryAll('script')) { 123 for (var tag in document.queryAll('script')) {
381 var src = tag.attributes['src']; 124 var src = tag.attributes['src'];
382 if (src != null) { 125 if (src != null) {
383 var last = src.split('/').last; 126 var last = src.split('/').last;
384 if (last == 'dart.js' || last == 'testing.js') { 127 if (last == 'dart.js' || last == 'testing.js') {
385 dartLoaderFound = true; 128 dartLoaderFound = true;
386 } else if (shadowDomJS.hasMatch(last)) { 129 } else if (_shadowDomJS.hasMatch(last)) {
387 shadowDomFound = true; 130 shadowDomFound = true;
388 } 131 }
389 } 132 }
390 if (tag.attributes['type'] == 'application/dart') { 133 if (tag.attributes['type'] == 'application/dart') {
391 tag.remove(); 134 tag.remove();
392 } else if (src != null) { 135 } else if (src != null) {
393 if (bootJS.hasMatch(src)) { 136 if (_bootJS.hasMatch(src)) {
394 tag.remove(); 137 tag.remove();
395 } else if (rewriteUrls) { 138 } else if (rewriteUrls) {
396 tag.attributes["src"] = pathMapper.transformUrl(filePath, src); 139 tag.attributes["src"] = pathMapper.transformUrl(filePath, src);
397 } 140 }
398 } 141 }
399 } 142 }
400 143
401 for (var tag in document.queryAll('link')) { 144 for (var tag in document.queryAll('link')) {
402 var href = tag.attributes['href']; 145 var href = tag.attributes['href'];
403 var rel = tag.attributes['rel']; 146 var rel = tag.attributes['rel'];
404 if (rel == 'component' || rel == 'components' || rel == 'import') { 147 if (rel == 'component' || rel == 'components' || rel == 'import') {
405 tag.remove(); 148 tag.remove();
406 } else if (href != null && rewriteUrls && !hasCss) { 149 } else if (href != null && rewriteUrls && !hasCss) {
407 // Only rewrite URL if rewrite on and we're not CSS polyfilling. 150 // Only rewrite URL if rewrite on and we're not CSS polyfilling.
408 tag.attributes['href'] = pathMapper.transformUrl(filePath, href); 151 tag.attributes['href'] = pathMapper.transformUrl(filePath, href);
409 } 152 }
410 } 153 }
411 154
412 if (rewriteUrls) { 155 if (rewriteUrls) {
413 // Transform any element's attribute which is a relative URL. 156 // Transform any element's attribute which is a relative URL.
414 _transformRelativeUrlAttributes(document, pathMapper, filePath); 157 new _AttributeUrlTransform(filePath, pathMapper).visit(document);
415 } 158 }
416 159
417 if (hasCss) { 160 if (hasCss) {
418 var newCss = pathMapper.mangle(path.basename(filePath), '.css', true); 161 var newCss = pathMapper.mangle(path.basename(filePath), '.css', true);
419 var linkElem = new Element.html( 162 var linkElem = new Element.html(
420 '<link rel="stylesheet" type="text/css" href="$newCss">'); 163 '<link rel="stylesheet" type="text/css" href="$newCss">');
421 document.head.insertBefore(linkElem, null); 164 document.head.insertBefore(linkElem, null);
422 } 165 }
423 166
424 var styles = document.queryAll('style'); 167 var styles = document.queryAll('style');
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
464 // 'Please add this line to your HTML file: $dartLoader', 207 // 'Please add this line to your HTML file: $dartLoader',
465 // document.body.sourceSpan); 208 // document.body.sourceSpan);
466 // TODO(sigmund): switch to 'boot.js' 209 // TODO(sigmund): switch to 'boot.js'
467 document.body.nodes.add(parseFragment('<script type="text/javascript" ' 210 document.body.nodes.add(parseFragment('<script type="text/javascript" '
468 'src="packages/browser/dart.js"></script>\n')); 211 'src="packages/browser/dart.js"></script>\n'));
469 } 212 }
470 213
471 // Insert the "auto-generated" comment after the doctype, otherwise IE will 214 // Insert the "auto-generated" comment after the doctype, otherwise IE will
472 // go into quirks mode. 215 // go into quirks mode.
473 int commentIndex = 0; 216 int commentIndex = 0;
474 DocumentType doctype = find(document.nodes, (n) => n is DocumentType); 217 DocumentType doctype =
218 document.nodes.firstWhere((n) => n is DocumentType, orElse: () => null);
475 if (doctype != null) { 219 if (doctype != null) {
476 commentIndex = document.nodes.indexOf(doctype) + 1; 220 commentIndex = document.nodes.indexOf(doctype) + 1;
477 // TODO(jmesserly): the html5lib parser emits a warning for missing 221 // TODO(jmesserly): the html5lib parser emits a warning for missing
478 // doctype, but it allows you to put it after comments. Presumably they do 222 // doctype, but it allows you to put it after comments. Presumably they do
479 // this because some comments won't force IE into quirks mode (sigh). See 223 // this because some comments won't force IE into quirks mode (sigh). See
480 // this link for more info: 224 // this link for more info:
481 // http://bugzilla.validator.nu/show_bug.cgi?id=836 225 // http://bugzilla.validator.nu/show_bug.cgi?id=836
482 // For simplicity we emit the warning always, like validator.nu does. 226 // For simplicity we emit the warning always, like validator.nu does.
483 if (doctype.tagName != 'html' || commentIndex != 1) { 227 if (doctype.tagName != 'html' || commentIndex != 1) {
484 messages.warning('file should start with <!DOCTYPE html> ' 228 messages.warning('file should start with <!DOCTYPE html> '
485 'to avoid the possibility of it being parsed in quirks mode in IE. ' 229 'to avoid the possibility of it being parsed in quirks mode in IE. '
486 'See http://www.w3.org/TR/html5-diff/#doctype', doctype.sourceSpan); 230 'See http://www.w3.org/TR/html5-diff/#doctype', doctype.sourceSpan);
487 } 231 }
488 } 232 }
489 document.nodes.insert(commentIndex, parseFragment( 233 document.nodes.insert(commentIndex, parseFragment(
490 '\n<!-- This file was auto-generated from $filePath. -->\n')); 234 '\n<!-- This file was auto-generated from $filePath. -->\n'));
491 } 235 }
492
493 /** Header with common imports, used in every generated .dart file. */
494 String _header(String filename, String libraryName) {
495 var lib = libraryName != null ? '\nlibrary $libraryName;\n' : '';
496 return """
497 // Auto-generated from $filename.
498 // DO NOT EDIT.
499 $lib
500 import 'dart:html' as autogenerated;
501 import 'dart:svg' as autogenerated_svg;
502 import 'package:mdv/mdv.dart' as autogenerated_mdv;
503 import 'package:observe/observe.dart' as __observe;
504 import 'package:polymer/polymer.dart' as autogenerated;
505 """;
506 }
OLDNEW
« no previous file with comments | « lib/src/dart_parser.dart ('k') | lib/src/files.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698