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

Side by Side Diff: pkg/polymer/lib/src/build/import_inliner.dart

Issue 162093002: fix imports link rel=stylesheet (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « pkg/polymer/lib/src/build/common.dart ('k') | pkg/polymer/lib/src/declaration.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) 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
11 import 'package:barback/barback.dart'; 11 import 'package:barback/barback.dart';
12 import 'package:path/path.dart' as path; 12 import 'package:path/path.dart' as path;
13 import 'package:html5lib/dom.dart' show 13 import 'package:html5lib/dom.dart' show
14 Document, DocumentFragment, Element, Node; 14 Document, DocumentFragment, Element, Node;
15 import 'package:html5lib/dom_parsing.dart' show TreeVisitor; 15 import 'package:html5lib/dom_parsing.dart' show TreeVisitor;
16 import 'package:source_maps/span.dart' show Span; 16 import 'package:source_maps/span.dart';
17 17
18 import 'code_extractor.dart'; // import just for documentation. 18 import 'code_extractor.dart'; // import just for documentation.
19 import 'common.dart'; 19 import 'common.dart';
20 20
21 class _HtmlInliner extends PolymerTransformer { 21 class _HtmlInliner extends PolymerTransformer {
22 final TransformOptions options; 22 final TransformOptions options;
23 final Transform transform; 23 final Transform transform;
24 final TransformLogger logger; 24 final TransformLogger logger;
25 final AssetId docId; 25 final AssetId docId;
26 final seen = new Set<AssetId>(); 26 final seen = new Set<AssetId>();
(...skipping 21 matching lines...) Expand all
48 } 48 }
49 49
50 // We produce a secondary asset with extra information for later phases. 50 // We produce a secondary asset with extra information for later phases.
51 transform.addOutput(new Asset.fromString( 51 transform.addOutput(new Asset.fromString(
52 docId.addExtension('.scriptUrls'), 52 docId.addExtension('.scriptUrls'),
53 JSON.encode(scriptIds, toEncodable: (id) => id.serialize()))); 53 JSON.encode(scriptIds, toEncodable: (id) => id.serialize())));
54 })); 54 }));
55 } 55 }
56 56
57 /** 57 /**
58 * Visits imports in [document] and add the imported documents to [documents]. 58 * Visits imports in [document] and add the imported documents to documents.
59 * Documents are added in the order they appear, transitive imports are added 59 * Documents are added in the order they appear, transitive imports are added
60 * first. 60 * first.
61 *
62 * Returns `true` if and only if the document was changed and should be
63 * written out.
61 */ 64 */
62 Future<bool> _visitImports(Document document, AssetId sourceId) { 65 Future<bool> _visitImports(Document document, AssetId sourceId) {
63 bool hasImports = false; 66 bool changed = false;
64 67
65 // Note: we need to preserve the import order in the generated output. 68 // Note: we need to preserve the import order in the generated output.
66 return Future.forEach(document.querySelectorAll('link'), (Element tag) { 69 return Future.forEach(document.querySelectorAll('link'), (Element tag) {
67 if (tag.attributes['rel'] != 'import') return null; 70 var rel = tag.attributes['rel'];
71 if (rel != 'import' && rel != 'stylesheet') return null;
72
68 var href = tag.attributes['href']; 73 var href = tag.attributes['href'];
69 var id = resolve(sourceId, href, transform.logger, tag.sourceSpan); 74 var id = resolve(sourceId, href, transform.logger, tag.sourceSpan,
70 hasImports = true; 75 allowAbsolute: rel == 'stylesheet');
71 76
72 tag.remove(); 77 if (rel == 'import') {
73 if (id == null || !seen.add(id) || 78 changed = true;
74 (id.package == 'polymer' && id.path == 'lib/init.html')) return null; 79 tag.remove();
80 if (id == null || !seen.add(id)) return null;
81 return _inlineImport(id);
75 82
76 return _inlineImport(id); 83 } else if (rel == 'stylesheet') {
77 }).then((_) => hasImports); 84 if (id == null) return null;
85 changed = true;
86 return _inlineStylesheet(id, tag);
87 }
88 }).then((_) => changed);
78 } 89 }
79 90
80 // Loads an asset identified by [id], visits its imports and collects its 91 // Loads an asset identified by [id], visits its imports and collects its
81 // html imports. Then inlines it into the main document. 92 // html imports. Then inlines it into the main document.
82 Future _inlineImport(AssetId id) => 93 Future _inlineImport(AssetId id) =>
83 readAsHtml(id, transform).then((doc) => _visitImports(doc, id).then((_) { 94 readAsHtml(id, transform).then((doc) => _visitImports(doc, id).then((_) {
84 95
85 new _UrlNormalizer(transform, id).visit(doc); 96 new _UrlNormalizer(transform, id).visit(doc);
86 _extractScripts(doc); 97 _extractScripts(doc);
87 98
88 // TODO(jmesserly): figure out how this is working in vulcanizer. 99 // TODO(jmesserly): figure out how this is working in vulcanizer.
89 // Do they produce a <body> tag with a <head> and <body> inside? 100 // Do they produce a <body> tag with a <head> and <body> inside?
90 imported.nodes 101 imported.nodes..addAll(doc.head.nodes)..addAll(doc.body.nodes);
91 ..addAll(doc.head.nodes)
92 ..addAll(doc.body.nodes);
93 })); 102 }));
94 103
104 Future _inlineStylesheet(AssetId id, Element link) {
105 return transform.readInputAsString(id).then((css) {
106 var url = spanUrlFor(id, transform);
107 css = new _UrlNormalizer(transform, id).visitCss(css, url);
108 link.replaceWith(new Element.tag('style')..text = css);
109 });
110 }
111
95 /** 112 /**
96 * Split Dart script tags from all the other elements. Now that Dartium 113 * Split Dart script tags from all the other elements. Now that Dartium
97 * only allows a single script tag per page, we can't inline script 114 * only allows a single script tag per page, we can't inline script
98 * tags. Instead, we collect the urls of each script tag so we import 115 * tags. Instead, we collect the urls of each script tag so we import
99 * them directly from the Dart bootstrap code. 116 * them directly from the Dart bootstrap code.
100 */ 117 */
101 void _extractScripts(Document document) { 118 void _extractScripts(Document document) {
102 bool first = true; 119 bool first = true;
103 for (var script in document.querySelectorAll('script')) { 120 for (var script in document.querySelectorAll('script')) {
104 if (script.attributes['type'] == 'application/dart') { 121 if (script.attributes['type'] == 'application/dart') {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 if (_urlAttributes.contains(key)) { 182 if (_urlAttributes.contains(key)) {
166 var url = node.attributes[key]; 183 var url = node.attributes[key];
167 if (url != null && url != '' && !url.startsWith('{{')) { 184 if (url != null && url != '' && !url.startsWith('{{')) {
168 node.attributes[key] = _newUrl(url, node.sourceSpan); 185 node.attributes[key] = _newUrl(url, node.sourceSpan);
169 } 186 }
170 } 187 }
171 } 188 }
172 super.visitElement(node); 189 super.visitElement(node);
173 } 190 }
174 191
192 static final _URL = new RegExp(r'url\(([^)]*)\)', multiLine: true);
193 static final _QUOTE = new RegExp('["\']', multiLine: true);
194
195 /** Visit the CSS text and replace any relative URLs so we can inline it. */
196 // Ported from:
197 // https://github.com/Polymer/vulcanize/blob/c14f63696797cda18dc3d372b78aa3378 acc691f/lib/vulcan.js#L149
198 // TODO(jmesserly): use csslib here instead? Parsing with RegEx is sadness.
199 // Maybe it's reliable enough for finding URLs in CSS? I'm not sure.
200 String visitCss(String cssText, String url) {
201 var src = new SourceFile.text(url, cssText);
202 return cssText.replaceAllMapped(_URL, (match) {
203 // Extract the URL, without any surrounding quotes.
204 var span = src.span(match.start, match.end);
205 var href = match[1].replaceAll(_QUOTE, '');
206 href = _newUrl(href, span);
207 return 'url($href)';
208 });
209 }
210
175 _newUrl(String href, Span span) { 211 _newUrl(String href, Span span) {
176 var uri = Uri.parse(href); 212 var uri = Uri.parse(href);
177 if (uri.isAbsolute) return href; 213 if (uri.isAbsolute) return href;
178 if (!uri.scheme.isEmpty) return href; 214 if (!uri.scheme.isEmpty) return href;
179 if (!uri.host.isEmpty) return href; 215 if (!uri.host.isEmpty) return href;
180 if (uri.path.isEmpty) return href; // Implies standalone ? or # in URI. 216 if (uri.path.isEmpty) return href; // Implies standalone ? or # in URI.
181 if (path.isAbsolute(href)) return href; 217 if (path.isAbsolute(href)) return href;
182 218
183 var id = resolve(sourceId, href, transform.logger, span); 219 var id = resolve(sourceId, href, transform.logger, span);
184 if (id == null) return href; 220 if (id == null) return href;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 'cite', // in blockquote, del, ins, q 254 'cite', // in blockquote, del, ins, q
219 'data', // in object 255 'data', // in object
220 'formaction', // in button, input 256 'formaction', // in button, input
221 'href', // in a, area, link, base, command 257 'href', // in a, area, link, base, command
222 'icon', // in command 258 'icon', // in command
223 'manifest', // in html 259 'manifest', // in html
224 'poster', // in video 260 'poster', // in video
225 'src', // in audio, embed, iframe, img, input, script, source, track, 261 'src', // in audio, embed, iframe, img, input, script, source, track,
226 // video 262 // video
227 ]; 263 ];
OLDNEW
« no previous file with comments | « pkg/polymer/lib/src/build/common.dart ('k') | pkg/polymer/lib/src/declaration.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698