OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 /// Transfomer that inlines polymer-element definitions from html imports. | 5 /// Transfomer that inlines polymer-element definitions from html imports. |
6 library polymer.src.build.import_inliner; | 6 library polymer.src.build.import_inliner; |
7 | 7 |
8 import 'dart:async'; | 8 import 'dart:async'; |
9 import 'dart:convert'; | 9 import 'dart:convert'; |
10 | 10 |
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 } | 410 } |
411 | 411 |
412 if (!output.hasEdits) return code; | 412 if (!output.hasEdits) return code; |
413 | 413 |
414 // TODO(sigmund): emit source maps when barback supports it (see | 414 // TODO(sigmund): emit source maps when barback supports it (see |
415 // dartbug.com/12340) | 415 // dartbug.com/12340) |
416 return (output.commit()..build(file.url)).text; | 416 return (output.commit()..build(file.url)).text; |
417 } | 417 } |
418 | 418 |
419 String _newUrl(String href, Span span) { | 419 String _newUrl(String href, Span span) { |
420 // Uri.parse blows up on invalid characters (like {{). Encoding the uri | 420 // Take all bindings out of the path and replace with [BINDING_PLACEHOLDER] |
421 // allows it to be parsed, which does the correct thing in the general case. | 421 // so [Uri.parse] will not fail. |
422 // This uri not used to build the new uri, so it never needs to be decoded. | 422 var bindingMatches = BINDING_REGEX.allMatches(href).map((m) => m.group(0)); |
423 var uri = Uri.parse(Uri.encodeFull(href)); | 423 href = href.replaceAll(BINDING_REGEX, BINDING_PLACEHOLDER); |
| 424 |
| 425 var uri = Uri.parse(href); |
424 if (uri.isAbsolute) return href; | 426 if (uri.isAbsolute) return href; |
425 if (!uri.scheme.isEmpty) return href; | 427 if (!uri.scheme.isEmpty) return href; |
426 if (!uri.host.isEmpty) return href; | 428 if (!uri.host.isEmpty) return href; |
427 if (uri.path.isEmpty) return href; // Implies standalone ? or # in URI. | 429 if (uri.path.isEmpty) return href; // Implies standalone ? or # in URI. |
428 if (path.isAbsolute(href)) return href; | 430 if (path.isAbsolute(href)) return href; |
429 | 431 |
430 var id = uriToAssetId(sourceId, href, transform.logger, span); | 432 var id = uriToAssetId(sourceId, href, transform.logger, span); |
431 if (id == null) return href; | 433 if (id == null) return href; |
432 var primaryId = transform.primaryInput.id; | 434 var primaryId = transform.primaryInput.id; |
433 | 435 |
434 if (id.path.startsWith('lib/')) { | 436 // Put the original bindings back into the path now that we have parsed it. |
435 return '${topLevelPath}packages/${id.package}/${id.path.substring(4)}'; | 437 var newPath = id.path; |
| 438 for (var bindingMatch in bindingMatches) { |
| 439 newPath = newPath.replaceFirst(BINDING_PLACEHOLDER, bindingMatch); |
436 } | 440 } |
437 | 441 |
438 if (id.path.startsWith('asset/')) { | 442 if (newPath.startsWith('lib/')) { |
439 return '${topLevelPath}assets/${id.package}/${id.path.substring(6)}'; | 443 return '${topLevelPath}packages/${id.package}/${newPath.substring(4)}'; |
| 444 } |
| 445 |
| 446 if (newPath.startsWith('asset/')) { |
| 447 return '${topLevelPath}assets/${id.package}/${newPath.substring(6)}'; |
440 } | 448 } |
441 | 449 |
442 if (primaryId.package != id.package) { | 450 if (primaryId.package != id.package) { |
443 // Techincally we shouldn't get there | 451 // Techincally we shouldn't get there |
444 transform.logger.error("don't know how to include $id from $primaryId", | 452 transform.logger.error("don't know how to include $id from $primaryId", |
445 span: span); | 453 span: span); |
446 return href; | 454 return href; |
447 } | 455 } |
448 | 456 |
449 var builder = path.url; | 457 var builder = path.url; |
450 return builder.relative(builder.join('/', id.path), | 458 return builder.relative(builder.join('/', newPath), |
451 from: builder.join('/', builder.dirname(primaryId.path))); | 459 from: builder.join('/', builder.dirname(primaryId.path))); |
452 } | 460 } |
453 } | 461 } |
454 | 462 |
455 /// HTML attributes that expect a URL value. | 463 /// HTML attributes that expect a URL value. |
456 /// <http://dev.w3.org/html5/spec/section-index.html#attributes-1> | 464 /// <http://dev.w3.org/html5/spec/section-index.html#attributes-1> |
457 /// | 465 /// |
458 /// Every one of these attributes is a URL in every context where it is used in | 466 /// Every one of these attributes is a URL in every context where it is used in |
459 /// the DOM. The comments show every DOM element where an attribute can be used. | 467 /// the DOM. The comments show every DOM element where an attribute can be used. |
460 const _urlAttributes = const [ | 468 const _urlAttributes = const [ |
461 'action', // in form | 469 'action', // in form |
462 'background', // in body | 470 'background', // in body |
463 'cite', // in blockquote, del, ins, q | 471 'cite', // in blockquote, del, ins, q |
464 'data', // in object | 472 'data', // in object |
465 'formaction', // in button, input | 473 'formaction', // in button, input |
466 'href', // in a, area, link, base, command | 474 'href', // in a, area, link, base, command |
467 'icon', // in command | 475 'icon', // in command |
468 'manifest', // in html | 476 'manifest', // in html |
469 'poster', // in video | 477 'poster', // in video |
470 'src', // in audio, embed, iframe, img, input, script, source, track, | 478 'src', // in audio, embed, iframe, img, input, script, source, track, |
471 // video | 479 // video |
472 ]; | 480 ]; |
473 | 481 |
474 /// When inlining <link rel="stylesheet"> tags copy over all attributes to the | 482 /// When inlining <link rel="stylesheet"> tags copy over all attributes to the |
475 /// style tag except these ones. | 483 /// style tag except these ones. |
476 const IGNORED_LINKED_STYLE_ATTRS = | 484 const IGNORED_LINKED_STYLE_ATTRS = |
477 const ['charset', 'href', 'href-lang', 'rel', 'rev']; | 485 const ['charset', 'href', 'href-lang', 'rel', 'rev']; |
478 | 486 |
479 /// Global RegExp objects for validating generated library names. | 487 /// Global RegExp objects. |
480 final INVALID_LIB_CHARS_REGEX = new RegExp('[^a-z0-9_]'); | 488 final INVALID_LIB_CHARS_REGEX = new RegExp('[^a-z0-9_]'); |
481 final NUM_REGEX = new RegExp('[0-9]'); | 489 final NUM_REGEX = new RegExp('[0-9]'); |
| 490 final BINDING_REGEX = new RegExp(r'({{.*}})'); |
| 491 |
| 492 /// Placeholder for bindings in urls for [Uri.parse]. |
| 493 final BINDING_PLACEHOLDER = '%BINDING%'; |
482 | 494 |
483 _getSpan(SourceFile file, AstNode node) => file.span(node.offset, node.end); | 495 _getSpan(SourceFile file, AstNode node) => file.span(node.offset, node.end); |
OLD | NEW |