1+ import  { DirectiveMetadata ,  SourceModule ,  ViewEncapsulation }  from  './api' ; 
2+ import  { XHR }  from  'angular2/src/core/render/xhr' ; 
3+ import  { StringWrapper ,  isJsObject ,  isBlank }  from  'angular2/src/core/facade/lang' ; 
4+ import  { PromiseWrapper ,  Promise }  from  'angular2/src/core/facade/async' ; 
5+ import  { ShadowCss }  from  'angular2/src/core/render/dom/compiler/shadow_css' ; 
6+ import  { UrlResolver }  from  'angular2/src/core/services/url_resolver' ; 
7+ import  { resolveStyleUrls }  from  './style_url_resolver' ; 
8+ 
9+ const  COMPONENT_VARIABLE  =  '%COMP%' ; 
10+ var  COMPONENT_REGEX  =  / % C O M P % / g; 
11+ const  HOST_ATTR  =  `_nghost-${ COMPONENT_VARIABLE }  ` ; 
12+ const  CONTENT_ATTR  =  `_ngcontent-${ COMPONENT_VARIABLE }  ` ; 
13+ var  ESCAPE_STRING_RE  =  / ' | \\ | \n / g; 
14+ var  IS_DART  =  ! isJsObject ( { } ) ; 
15+ 
16+ export  class  StyleCompiler  { 
17+   private  _styleCache : Map < string ,  Promise < string [ ] > >  =  new  Map < string ,  Promise < string [ ] > > ( ) ; 
18+   private  _shadowCss : ShadowCss  =  new  ShadowCss ( ) ; 
19+ 
20+   constructor ( private  _xhr : XHR ,  private  _urlResolver : UrlResolver )  { } 
21+ 
22+   compileComponentRuntime ( component : DirectiveMetadata ) : Promise < string [ ] >  { 
23+     var  styles  =  component . template . styles ; 
24+     var  styleAbsUrls  =  component . template . styleAbsUrls ; 
25+     return  this . _loadStyles ( styles ,  styleAbsUrls , 
26+                             component . template . encapsulation  ===  ViewEncapsulation . Emulated ) 
27+         . then ( styles  =>  styles . map ( style  =>  StringWrapper . replaceAll ( style ,  COMPONENT_REGEX , 
28+                                                                      `${ component . type . id }  ` ) ) ) ; 
29+   } 
30+ 
31+   compileComponentCodeGen ( component : DirectiveMetadata ) : SourceModule  { 
32+     var  shim  =  component . template . encapsulation  ===  ViewEncapsulation . Emulated ; 
33+     var  suffix ; 
34+     if  ( shim )  { 
35+       var  componentId  =  `${  component . type . id }  ` ; 
36+       suffix  = 
37+           codeGenMapArray ( [ 'style' ] ,  `style${ codeGenReplaceAll ( COMPONENT_VARIABLE ,  componentId ) }  ` ) ; 
38+     }  else  { 
39+       suffix  =  '' ; 
40+     } 
41+     return  this . _styleCodeGen ( `$component.type.typeUrl}.styles` ,  component . template . styles , 
42+                               component . template . styleAbsUrls ,  shim ,  suffix ) ; 
43+   } 
44+ 
45+   compileStylesheetCodeGen ( moduleName : string ,  cssText : string ) : SourceModule [ ]  { 
46+     var  styleWithImports  =  resolveStyleUrls ( this . _urlResolver ,  moduleName ,  cssText ) ; 
47+     return  [ 
48+       this . _styleCodeGen ( moduleName ,  [ styleWithImports . style ] ,  styleWithImports . styleUrls ,  false , 
49+                          '' ) , 
50+       this . _styleCodeGen ( moduleName ,  [ styleWithImports . style ] ,  styleWithImports . styleUrls ,  true ,  '' ) 
51+     ] ; 
52+   } 
53+ 
54+   private  _loadStyles ( plainStyles : string [ ] ,  absUrls : string [ ] , 
55+                       encapsulate : boolean ) : Promise < string [ ] >  { 
56+     var  promises  =  absUrls . map ( ( absUrl )  =>  { 
57+       var  cacheKey  =  `${ absUrl } ${ encapsulate  ? '.shim'  : '' }  ` ; 
58+       var  result  =  this . _styleCache . get ( cacheKey ) ; 
59+       if  ( isBlank ( result ) )  { 
60+         result  =  this . _xhr . get ( absUrl ) . then ( ( style )  =>  { 
61+           var  styleWithImports  =  resolveStyleUrls ( this . _urlResolver ,  absUrl ,  style ) ; 
62+           return  this . _loadStyles ( [ styleWithImports . style ] ,  styleWithImports . styleUrls , 
63+                                   encapsulate ) ; 
64+         } ) ; 
65+         this . _styleCache . set ( cacheKey ,  result ) ; 
66+       } 
67+       return  result ; 
68+     } ) ; 
69+     return  PromiseWrapper . all ( promises ) . then ( ( nestedStyles : string [ ] [ ] )  =>  { 
70+       var  result  =  plainStyles . map ( plainStyle  =>  this . _shimIfNeeded ( plainStyle ,  encapsulate ) ) ; 
71+       nestedStyles . forEach ( styles  =>  styles . forEach ( style  =>  result . push ( style ) ) ) ; 
72+       return  result ; 
73+     } ) ; 
74+   } 
75+ 
76+   private  _styleCodeGen ( moduleName : string ,  plainStyles : string [ ] ,  absUrls : string [ ] ,  shim : boolean , 
77+                         suffix : string ) : SourceModule  { 
78+     var  imports : string [ ] [ ]  =  [ ] ; 
79+     var  moduleSource  =  `${ codeGenExportVar ( 'STYLES' ) }   (` ; 
80+     moduleSource  += 
81+         `[${ plainStyles . map (  plainStyle  =>  escapeString ( this . _shimIfNeeded ( plainStyle ,  shim ) )  ) . join ( ',' ) }  ]` ; 
82+     for  ( var  i  =  0 ;  i  <  absUrls . length ;  i ++ )  { 
83+       var  url  =  absUrls [ i ] ; 
84+       var  moduleAlias  =  `import${ i }  ` ; 
85+       imports . push ( [ this . _shimModuleName ( url ,  shim ) ,  moduleAlias ] ) ; 
86+       moduleSource  +=  `${ codeGenConcatArray ( moduleAlias + '.STYLES' ) }  ` ; 
87+     } 
88+     moduleSource  +=  `)${ suffix }  ;` ; 
89+     return  new  SourceModule ( this . _shimModuleName ( moduleName ,  shim ) ,  moduleSource ,  imports ) ; 
90+   } 
91+ 
92+   private  _shimIfNeeded ( style : string ,  shim : boolean ) : string  { 
93+     return  shim  ? this . _shadowCss . shimCssText ( style ,  CONTENT_ATTR ,  HOST_ATTR )  : style ; 
94+   } 
95+ 
96+   private  _shimModuleName ( originalUrl : string ,  shim : boolean ) : string  { 
97+     return  shim  ? `${ originalUrl }  .shim`  : originalUrl ; 
98+   } 
99+ } 
100+ 
101+ function  escapeString ( input : string ) : string  { 
102+   var  escapedInput  =  StringWrapper . replaceAllMapped ( input ,  ESCAPE_STRING_RE ,  ( match )  =>  { 
103+     if  ( match [ 0 ]  ==  "'"  ||  match [ 0 ]  ==  '\\' )  { 
104+       return  `\\${ match [ 0 ] }  ` ; 
105+     }  else  { 
106+       return  '\\n' ; 
107+     } 
108+   } ) ; 
109+   return  `'${ escapedInput }  '` ; 
110+ } 
111+ 
112+ function  codeGenExportVar ( name : string ) : string  { 
113+   if  ( IS_DART )  { 
114+     return  `var ${ name }   =` ; 
115+   }  else  { 
116+     return  `var ${ name }   = exports.${ name }   =` ; 
117+   } 
118+ } 
119+ 
120+ function  codeGenConcatArray ( expression : string ) : string  { 
121+   return  `${ IS_DART  ? '..addAll'  : '.concat' }  (${ expression }  )` ; 
122+ } 
123+ 
124+ function  codeGenMapArray ( argNames : string [ ] ,  callback : string ) : string  { 
125+   if  ( IS_DART )  { 
126+     return  `.map( (${ argNames . join ( ',' ) }  ) => ${ callback }   ).toList()` ; 
127+   }  else  { 
128+     return  `.map(function(${ argNames . join ( ',' ) }  ) { return ${ callback }  ; })` ; 
129+   } 
130+ } 
131+ 
132+ function  codeGenReplaceAll ( pattern : string ,  value : string ) : string  { 
133+   if  ( IS_DART )  { 
134+     return  `.replaceAll('${ pattern }  ', '${ value }  ')` ; 
135+   }  else  { 
136+     return  `.replace(/${ pattern }  /g, '${ value }  ')` ; 
137+   } 
138+ } 
0 commit comments