@@ -30,7 +30,7 @@ class ShadowDomComponentFactory implements ComponentFactory {
30
30
31
31
ShadowDomComponentFactory (this ._expando);
32
32
33
- final Map <String , async.Future <dom.StyleElement >> _styleElementCache = {};
33
+ final Map <_ComponentAssetKey , async.Future <dom.StyleElement >> _styleElementCache = {};
34
34
35
35
FactoryFn call (dom.Node node, DirectiveRef ref) {
36
36
return (Injector injector) {
@@ -42,8 +42,15 @@ class ShadowDomComponentFactory implements ComponentFactory {
42
42
DirectiveMap directives = injector.get (DirectiveMap );
43
43
NgBaseCss baseCss = injector.get (NgBaseCss );
44
44
// This is a bit of a hack since we are returning different type then we are.
45
- var componentFactory = new _ComponentFactory (node, ref.type, component,
46
- injector.get (dom.NodeTreeSanitizer ), _expando, baseCss, _styleElementCache);
45
+ var componentFactory = new _ComponentFactory (node,
46
+ ref.type,
47
+ component,
48
+ injector.get (dom.NodeTreeSanitizer ),
49
+ injector.get (WebPlatform ),
50
+ injector.get (ComponentCssRewriter ),
51
+ _expando,
52
+ baseCss,
53
+ _styleElementCache);
47
54
var controller = componentFactory.call (injector, scope, viewCache, http, templateCache,
48
55
directives);
49
56
@@ -67,15 +74,19 @@ class _ComponentFactory implements Function {
67
74
final dom.NodeTreeSanitizer treeSanitizer;
68
75
final Expando _expando;
69
76
final NgBaseCss _baseCss;
70
- final Map <String , async.Future <dom.StyleElement >> _styleElementCache;
77
+ final Map <_ComponentAssetKey , async.Future <dom.StyleElement >>
78
+ _styleElementCache;
79
+ final ComponentCssRewriter componentCssRewriter;
80
+ final WebPlatform platform;
71
81
72
82
dom.ShadowRoot shadowDom;
73
83
Scope shadowScope;
74
84
Injector shadowInjector;
75
85
var controller;
76
86
77
87
_ComponentFactory (this .element, this .type, this .component, this .treeSanitizer,
78
- this ._expando, this ._baseCss, this ._styleElementCache);
88
+ this .platform, this .componentCssRewriter, this ._expando,
89
+ this ._baseCss, this ._styleElementCache);
79
90
80
91
dynamic call (Injector injector, Scope scope,
81
92
ViewCache viewCache, Http http, TemplateCache templateCache,
@@ -92,22 +103,57 @@ class _ComponentFactory implements Function {
92
103
// better work around is found.
93
104
Iterable <async.Future <dom.StyleElement >> cssFutures;
94
105
var cssUrls = []..addAll (_baseCss.urls)..addAll (component.cssUrls);
106
+ var tag = element.tagName.toLowerCase ();
95
107
if (cssUrls.isNotEmpty) {
96
- cssFutures = cssUrls.map ((cssUrl) => _styleElementCache.putIfAbsent (cssUrl, () =>
108
+ cssFutures = cssUrls.map ((cssUrl) => _styleElementCache.putIfAbsent (
109
+ new _ComponentAssetKey (tag, cssUrl), () =>
97
110
http.get (cssUrl, cache: templateCache)
98
111
.then ((resp) => resp.responseText,
99
112
onError: (e) => '/*\n $e \n */\n ' )
100
- .then ((styleContent) => new dom.StyleElement ()..appendText (styleContent))
113
+ .then ((String css) {
114
+
115
+ // Shim CSS if required
116
+ if (platform.cssShimRequired) {
117
+ css = platform.shimCss (css, selector: tag, cssUrl: cssUrl);
118
+ }
119
+
120
+ // If a css rewriter is installed, run the css through a rewriter
121
+ var styleElement = new dom.StyleElement ()
122
+ ..appendText (componentCssRewriter (css, selector: tag,
123
+ cssUrl: cssUrl));
124
+
125
+ // ensure there are no invalid tags or modifications
126
+ treeSanitizer.sanitizeTree (styleElement);
127
+
128
+ // If the css shim is required, it means that scoping does not
129
+ // work, and adding the style to the head of the document is
130
+ // preferrable.
131
+ if (platform.cssShimRequired) {
132
+ dom.document.head.append (styleElement);
133
+ }
134
+
135
+ return styleElement;
136
+ })
101
137
)).toList ();
102
138
} else {
103
139
cssFutures = [new async .Future .value (null )];
104
140
}
105
- var viewFuture = ComponentFactory ._viewFuture (component, viewCache, directives);
141
+
142
+ var platformViewCache = new PlatformViewCache (viewCache, tag, platform);
143
+
144
+ var viewFuture = ComponentFactory ._viewFuture (component, platformViewCache,
145
+ directives);
146
+
106
147
TemplateLoader templateLoader = new TemplateLoader (
107
148
async .Future .wait (cssFutures).then ((Iterable <dom.StyleElement > cssList) {
108
- cssList
109
- .where ((styleElement) => styleElement != null )
110
- .forEach ((styleElement) => shadowDom.append (styleElement.clone (true )));
149
+ // This prevents style duplication by only adding css to the shadow
150
+ // root if there is a native implementation of shadow dom.
151
+ if (! platform.cssShimRequired) {
152
+ cssList.where ((styleElement) => styleElement != null )
153
+ .forEach ((styleElement) {
154
+ shadowDom.append (styleElement.clone (true ));
155
+ });
156
+ }
111
157
if (viewFuture != null ) {
112
158
return viewFuture.then ((ViewFactory viewFactory) {
113
159
return (! shadowScope.isAttached) ?
@@ -144,3 +190,33 @@ class _ComponentFactory implements Function {
144
190
return shadowInjector;
145
191
}
146
192
}
193
+
194
+ class _ComponentAssetKey {
195
+ final String tag;
196
+ final String assetUrl;
197
+
198
+ final String _key;
199
+
200
+ _ComponentAssetKey (String tag, String assetUrl)
201
+ : _key = "$tag |$assetUrl " ,
202
+ this .tag = tag,
203
+ this .assetUrl = assetUrl;
204
+
205
+ @override
206
+ String toString () => _key;
207
+
208
+ @override
209
+ int get hashCode => _key.hashCode;
210
+
211
+ bool operator == (key) =>
212
+ key is _ComponentAssetKey
213
+ && tag == key.tag
214
+ && assetUrl == key.assetUrl;
215
+ }
216
+
217
+ @Injectable ()
218
+ class ComponentCssRewriter {
219
+ String call (String css, { String selector, String cssUrl} ) {
220
+ return css;
221
+ }
222
+ }
0 commit comments