Skip to content

Commit 9a95d18

Browse files
author
John Messerly
committed
fixes #182, avoid injecting a duplicate link rel=stylesheet
[email protected] Review URL: https://codereview.chromium.org/1145893008
1 parent e15f53d commit 9a95d18

File tree

3 files changed

+42
-17
lines changed

3 files changed

+42
-17
lines changed

pkg/dev_compiler/lib/src/codegen/html_codegen.dart

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,26 +43,44 @@ String generateEntryHtml(HtmlSourceNode root, CompilerOptions options) {
4343
if (options.outputDart) return '${document.outerHtml}\n';
4444

4545
var libraries = [];
46-
var resources = [];
46+
var resources = new Set();
4747
visitInPostOrder(root, (n) {
4848
if (n is DartSourceNode) libraries.add(n);
4949
if (n is ResourceSourceNode) resources.add(n);
5050
}, includeParts: false);
5151

52-
String mainLibraryName;
52+
root.htmlResourceNodes.forEach((element, resource) {
53+
// Make sure we don't try and add this node again.
54+
resources.remove(resource);
55+
56+
var resourcePath = resourceOutputPath(resource.uri, root.uri);
57+
if (resource.cachingHash != null) {
58+
resourcePath = _addHash(resourcePath, resource.cachingHash);
59+
}
60+
var attrs = element.attributes;
61+
if (attrs.containsKey('href')) {
62+
attrs['href'] = resourcePath;
63+
} else if (attrs.containsKey('src')) {
64+
attrs['src'] = resourcePath;
65+
}
66+
});
67+
5368
var fragment = new DocumentFragment();
5469
for (var resource in resources) {
5570
var resourcePath = resourceOutputPath(resource.uri, root.uri);
5671
var ext = path.extension(resourcePath);
5772
if (resource.cachingHash != null) {
5873
resourcePath = _addHash(resourcePath, resource.cachingHash);
5974
}
60-
if (ext == '.css') {
61-
fragment.nodes.add(_cssInclude(resourcePath));
62-
} else if (ext == '.js') {
75+
if (ext == '.js') {
6376
fragment.nodes.add(_libraryInclude(resourcePath));
77+
} else if (ext == '.css') {
78+
var stylesheetLink = '<link rel="stylesheet" href="$resourcePath">\n';
79+
fragment.nodes.add(parseFragment(stylesheetLink));
6480
}
6581
}
82+
83+
String mainLibraryName;
6684
for (var lib in libraries) {
6785
var info = lib.info;
6886
if (info == null) continue;
@@ -82,10 +100,6 @@ String generateEntryHtml(HtmlSourceNode root, CompilerOptions options) {
82100
Node _libraryInclude(String jsUrl) =>
83101
parseFragment('<script src="$jsUrl"></script>\n');
84102

85-
/// A tag that loads the .css code.
86-
Node _cssInclude(String cssUrl) =>
87-
parseFragment('<link rel="stylesheet" href="$cssUrl">\n');
88-
89103
/// A script tag that invokes the main function on the entry point library.
90104
Node _invokeMain(String mainLibraryName) {
91105
var code = mainLibraryName == null

pkg/dev_compiler/lib/src/dependency_graph.dart

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
/// Tracks the shape of the import/export graph and dependencies between files.
66
library dev_compiler.src.dependency_graph;
77

8-
import 'dart:collection' show HashSet;
8+
import 'dart:collection' show HashSet, HashMap;
99

1010
import 'package:analyzer/analyzer.dart' show parseDirectives;
1111
import 'package:analyzer/src/generated/ast.dart'
@@ -21,7 +21,7 @@ import 'package:analyzer/src/generated/ast.dart'
2121
import 'package:analyzer/src/generated/engine.dart'
2222
show ParseDartTask, AnalysisContext;
2323
import 'package:analyzer/src/generated/source.dart' show Source, SourceKind;
24-
import 'package:html/dom.dart' show Document, Node;
24+
import 'package:html/dom.dart' show Document, Node, Element;
2525
import 'package:html/parser.dart' as html;
2626
import 'package:logging/logging.dart' show Logger, Level;
2727
import 'package:path/path.dart' as path;
@@ -167,6 +167,10 @@ class HtmlSourceNode extends SourceNode {
167167
/// Parsed document, updated whenever [update] is invoked.
168168
Document document;
169169

170+
/// Tracks resource files referenced from HTML nodes, e.g.
171+
/// `<link rel=stylesheet href=...>` and `<img src=...>`
172+
final htmlResourceNodes = new HashMap<Element, ResourceSourceNode>();
173+
170174
HtmlSourceNode(SourceGraph graph, Uri uri, Source source)
171175
: runtimeDeps = graph.runtimeDeps,
172176
super(graph, uri, source);
@@ -199,16 +203,24 @@ class HtmlSourceNode extends SourceNode {
199203
scripts = newScripts;
200204
}
201205

206+
// TODO(jmesserly): simplify the design here. Ideally we wouldn't need
207+
// to track user-defined CSS, images, etc. Also we don't have a clear
208+
// way to distinguish runtime injected resources, like messages.css, from
209+
// user-defined files.
210+
htmlResourceNodes.clear();
202211
var newResources = new Set<SourceNode>();
203212
for (var resource in graph.resources) {
204213
newResources.add(graph.nodeFromUri(uri.resolve(resource)));
205214
}
206215
for (var tag in document.querySelectorAll('link[rel="stylesheet"]')) {
207-
newResources
208-
.add(graph.nodeFromUri(uri.resolve(tag.attributes['href'])));
216+
var res = graph.nodeFromUri(uri.resolve(tag.attributes['href']));
217+
htmlResourceNodes[tag] = res;
218+
newResources.add(res);
209219
}
210-
for (var tag in document.querySelectorAll('img')) {
211-
newResources.add(graph.nodeFromUri(uri.resolve(tag.attributes['src'])));
220+
for (var tag in document.querySelectorAll('img[src]')) {
221+
var res = graph.nodeFromUri(uri.resolve(tag.attributes['src']));
222+
htmlResourceNodes[tag] = res;
223+
newResources.add(res);
212224
}
213225
if (!_same(newResources, resources)) {
214226
structureChanged = true;

pkg/dev_compiler/test/codegen/expect/sunflower/sunflower.html

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ <h1>drfibonacci's Sunflower Spectacular</h1>
2323
<p id="notes"> </p>
2424
</footer>
2525

26-
<link rel="stylesheet" href="sunflower.css">
27-
<script src="dev_compiler/runtime/harmony_feature_check.js"></script>
26+
<script src="dev_compiler/runtime/harmony_feature_check.js"></script>
2827
<script src="dev_compiler/runtime/dart_runtime.js"></script>
2928
<script src="dev_compiler/runtime/dart/core.js"></script>
3029
<script src="dev_compiler/runtime/dart/collection.js"></script>

0 commit comments

Comments
 (0)