2
2
MIT License http://www.opensource.org/licenses/mit-license.php
3
3
Author Tobias Koppers @sokra
4
4
*/
5
- var stylesInDom = { } ;
5
+ var stylesInDom = { } ,
6
+ memoize = function ( fn ) {
7
+ var memo ;
8
+ return function ( ) {
9
+ if ( typeof memo === "undefined" ) memo = fn . apply ( this , arguments ) ;
10
+ return memo ;
11
+ } ;
12
+ } ,
13
+ isIE9 = memoize ( function ( ) {
14
+ return / m s i e 9 \b / . test ( window . navigator . userAgent . toLowerCase ( ) ) ;
15
+ } ) ,
16
+ getHeadElement = memoize ( function ( ) {
17
+ return document . head || document . getElementsByTagName ( "head" ) [ 0 ] ;
18
+ } ) ,
19
+ singletonElement = null ,
20
+ singletonCounter = 0 ;
6
21
7
- module . exports = function ( list ) {
22
+ module . exports = function ( list , options ) {
8
23
if ( typeof DEBUG !== "undefined" && DEBUG ) {
9
24
if ( typeof document !== "object" ) throw new Error ( "The style-loader cannot be used in a non-browser environment" ) ;
10
25
}
26
+
27
+ options = options || { } ;
28
+ // Force single-tag solution on IE9, which has a hard limit on the # of <style>
29
+ // tags it will allow on a page
30
+ if ( typeof options . singleton === "undefined" ) options . singleton = isIE9 ( ) ;
31
+
11
32
var styles = listToStyles ( list ) ;
12
- addStylesToDom ( styles ) ;
33
+ addStylesToDom ( styles , options ) ;
34
+
13
35
return function update ( newList ) {
14
36
var mayRemove = [ ] ;
15
37
for ( var i = 0 ; i < styles . length ; i ++ ) {
@@ -20,7 +42,7 @@ module.exports = function(list) {
20
42
}
21
43
if ( newList ) {
22
44
var newStyles = listToStyles ( newList ) ;
23
- addStylesToDom ( newStyles ) ;
45
+ addStylesToDom ( newStyles , options ) ;
24
46
}
25
47
for ( var i = 0 ; i < mayRemove . length ; i ++ ) {
26
48
var domStyle = mayRemove [ i ] ;
@@ -33,7 +55,7 @@ module.exports = function(list) {
33
55
} ;
34
56
}
35
57
36
- function addStylesToDom ( styles ) {
58
+ function addStylesToDom ( styles , options ) {
37
59
for ( var i = 0 ; i < styles . length ; i ++ ) {
38
60
var item = styles [ i ] ;
39
61
var domStyle = stylesInDom [ item . id ] ;
@@ -43,12 +65,12 @@ function addStylesToDom(styles) {
43
65
domStyle . parts [ j ] ( item . parts [ j ] ) ;
44
66
}
45
67
for ( ; j < item . parts . length ; j ++ ) {
46
- domStyle . parts . push ( addStyle ( item . parts [ j ] ) ) ;
68
+ domStyle . parts . push ( addStyle ( item . parts [ j ] , options ) ) ;
47
69
}
48
70
} else {
49
71
var parts = [ ] ;
50
72
for ( var j = 0 ; j < item . parts . length ; j ++ ) {
51
- parts . push ( addStyle ( item . parts [ j ] ) ) ;
73
+ parts . push ( addStyle ( item . parts [ j ] , options ) ) ;
52
74
}
53
75
stylesInDom [ item . id ] = { id : item . id , refs : 1 , parts : parts } ;
54
76
}
@@ -73,44 +95,95 @@ function listToStyles(list) {
73
95
return styles ;
74
96
}
75
97
76
- function addStyle ( obj ) {
98
+ function createStyleElement ( ) {
77
99
var styleElement = document . createElement ( "style" ) ;
78
- var head = document . head || document . getElementsByTagName ( "head" ) [ 0 ] ;
100
+ var head = getHeadElement ( ) ;
79
101
styleElement . type = "text/css" ;
80
102
head . appendChild ( styleElement ) ;
81
- applyToTag ( styleElement , obj ) ;
82
- return function ( newObj ) {
103
+ return styleElement ;
104
+ }
105
+
106
+ function addStyle ( obj , options ) {
107
+ var styleElement , update , remove ;
108
+
109
+ if ( options . singleton ) {
110
+ var styleIndex = singletonCounter ++ ;
111
+ styleElement = singletonElement || ( singletonElement = createStyleElement ( ) ) ;
112
+ update = applyToSingletonTag . bind ( null , styleElement , styleIndex , false ) ;
113
+ remove = applyToSingletonTag . bind ( null , styleElement , styleIndex , true ) ;
114
+ } else {
115
+ styleElement = createStyleElement ( ) ;
116
+ update = applyToTag . bind ( null , styleElement ) ;
117
+ remove = function ( ) {
118
+ styleElement . parentNode . removeChild ( styleElement ) ;
119
+ } ;
120
+ }
121
+
122
+ update ( obj ) ;
123
+
124
+ return function updateStyle ( newObj ) {
83
125
if ( newObj ) {
84
126
if ( newObj . css === obj . css && newObj . media === obj . media /*&& newObj.sourceMap === obj.sourceMap*/ )
85
127
return ;
86
- applyToTag ( styleElement , obj = newObj ) ;
128
+ update ( obj = newObj ) ;
87
129
} else {
88
- head . removeChild ( styleElement ) ;
130
+ remove ( ) ;
89
131
}
90
132
} ;
91
- } ;
133
+ }
134
+
135
+ function replaceText ( source , id , replacement ) {
136
+ var boundaries = [ "/** >>" + id + " **/" , "/** " + id + "<< **/" ] ;
137
+ var start = source . lastIndexOf ( boundaries [ 0 ] ) ;
138
+ var wrappedReplacement = replacement
139
+ ? ( boundaries [ 0 ] + replacement + boundaries [ 1 ] )
140
+ : "" ;
141
+ if ( source . lastIndexOf ( boundaries [ 0 ] ) >= 0 ) {
142
+ var end = source . lastIndexOf ( boundaries [ 1 ] ) + boundaries [ 1 ] . length ;
143
+ return source . slice ( 0 , start ) + wrappedReplacement + source . slice ( end ) ;
144
+ } else {
145
+ return source + wrappedReplacement ;
146
+ }
147
+ }
148
+
149
+ function applyToSingletonTag ( styleElement , index , remove , obj ) {
150
+ var css = remove ? "" : obj . css ;
151
+
152
+ if ( styleElement . styleSheet ) {
153
+ styleElement . styleSheet . cssText = replaceText ( styleElement . styleSheet . cssText , index , css ) ;
154
+ } else {
155
+ var cssNode = document . createTextNode ( css ) ;
156
+ var childNodes = styleElement . childNodes ;
157
+ if ( childNodes [ index ] ) styleElement . removeChild ( childNodes [ index ] ) ;
158
+ if ( childNodes . length ) {
159
+ styleElement . insertBefore ( cssNode , childNodes [ index ] ) ;
160
+ } else {
161
+ styleElement . appendChild ( cssNode ) ;
162
+ }
163
+ }
164
+ }
92
165
93
166
function applyToTag ( styleElement , obj ) {
94
167
var css = obj . css ;
95
168
var media = obj . media ;
96
169
// var sourceMap = obj.sourceMap;
97
-
98
170
// No browser support
99
171
// if(sourceMap && typeof btoa === "function") {
100
172
// try {
101
173
// css += "\n/*# sourceMappingURL=data:application/json;base64," + btoa(JSON.stringify(sourceMap)) + " */";
102
174
// } catch(e) {}
103
175
// }
176
+
104
177
if ( media ) {
105
178
styleElement . setAttribute ( "media" , media )
106
179
}
107
- if ( styleElement . styleSheet ) {
180
+
181
+ if ( styleElement . styleSheet ) {
108
182
styleElement . styleSheet . cssText = css ;
109
183
} else {
110
184
while ( styleElement . firstChild ) {
111
185
styleElement . removeChild ( styleElement . firstChild ) ;
112
186
}
113
187
styleElement . appendChild ( document . createTextNode ( css ) ) ;
114
188
}
115
-
116
189
}
0 commit comments