UNPKG

6.02 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5var 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 isOldIE = memoize(function() {
14 return /msie [6-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;
21
22module.exports = function(list, options) {
23 if(typeof DEBUG !== "undefined" && DEBUG) {
24 if(typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment");
25 }
26
27 options = options || {};
28 // Force single-tag solution on IE6-9, 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 = isOldIE();
31
32 var styles = listToStyles(list);
33 addStylesToDom(styles, options);
34
35 return function update(newList) {
36 var mayRemove = [];
37 for(var i = 0; i < styles.length; i++) {
38 var item = styles[i];
39 var domStyle = stylesInDom[item.id];
40 domStyle.refs--;
41 mayRemove.push(domStyle);
42 }
43 if(newList) {
44 var newStyles = listToStyles(newList);
45 addStylesToDom(newStyles, options);
46 }
47 for(var i = 0; i < mayRemove.length; i++) {
48 var domStyle = mayRemove[i];
49 if(domStyle.refs === 0) {
50 for(var j = 0; j < domStyle.parts.length; j++)
51 domStyle.parts[j]();
52 delete stylesInDom[domStyle.id];
53 }
54 }
55 };
56}
57
58function addStylesToDom(styles, options) {
59 for(var i = 0; i < styles.length; i++) {
60 var item = styles[i];
61 var domStyle = stylesInDom[item.id];
62 if(domStyle) {
63 domStyle.refs++;
64 for(var j = 0; j < domStyle.parts.length; j++) {
65 domStyle.parts[j](item.parts[j]);
66 }
67 for(; j < item.parts.length; j++) {
68 domStyle.parts.push(addStyle(item.parts[j], options));
69 }
70 } else {
71 var parts = [];
72 for(var j = 0; j < item.parts.length; j++) {
73 parts.push(addStyle(item.parts[j], options));
74 }
75 stylesInDom[item.id] = {id: item.id, refs: 1, parts: parts};
76 }
77 }
78}
79
80function listToStyles(list) {
81 var styles = [];
82 var newStyles = {};
83 for(var i = 0; i < list.length; i++) {
84 var item = list[i];
85 var id = item[0];
86 var css = item[1];
87 var media = item[2];
88 var sourceMap = item[3];
89 var part = {css: css, media: media, sourceMap: sourceMap};
90 if(!newStyles[id])
91 styles.push(newStyles[id] = {id: id, parts: [part]});
92 else
93 newStyles[id].parts.push(part);
94 }
95 return styles;
96}
97
98function createStyleElement() {
99 var styleElement = document.createElement("style");
100 var head = getHeadElement();
101 styleElement.type = "text/css";
102 head.appendChild(styleElement);
103 return styleElement;
104}
105
106function createLinkElement() {
107 var linkElement = document.createElement("link");
108 var head = getHeadElement();
109 linkElement.rel = "stylesheet";
110 head.appendChild(linkElement);
111 return linkElement;
112}
113
114function addStyle(obj, options) {
115 var styleElement, update, remove;
116
117 if (options.singleton) {
118 var styleIndex = singletonCounter++;
119 styleElement = singletonElement || (singletonElement = createStyleElement());
120 update = applyToSingletonTag.bind(null, styleElement, styleIndex, false);
121 remove = applyToSingletonTag.bind(null, styleElement, styleIndex, true);
122 } else if(obj.sourceMap &&
123 typeof URL === "function" &&
124 typeof URL.createObjectURL === "function" &&
125 typeof URL.revokeObjectURL === "function" &&
126 typeof Blob === "function" &&
127 typeof btoa === "function") {
128 styleElement = createLinkElement();
129 update = updateLink.bind(null, styleElement);
130 remove = function() {
131 styleElement.parentNode.removeChild(styleElement);
132 if(styleElement.href)
133 URL.revokeObjectURL(styleElement.href);
134 };
135 } else {
136 styleElement = createStyleElement();
137 update = applyToTag.bind(null, styleElement);
138 remove = function() {
139 styleElement.parentNode.removeChild(styleElement);
140 };
141 }
142
143 update(obj);
144
145 return function updateStyle(newObj) {
146 if(newObj) {
147 if(newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap)
148 return;
149 update(obj = newObj);
150 } else {
151 remove();
152 }
153 };
154}
155
156var replaceText = (function () {
157 var textStore = [];
158
159 return function (index, replacement) {
160 textStore[index] = replacement;
161 return textStore.filter(Boolean).join('\n');
162 };
163})();
164
165function applyToSingletonTag(styleElement, index, remove, obj) {
166 var css = remove ? "" : obj.css;
167
168 if (styleElement.styleSheet) {
169 styleElement.styleSheet.cssText = replaceText(index, css);
170 } else {
171 var cssNode = document.createTextNode(css);
172 var childNodes = styleElement.childNodes;
173 if (childNodes[index]) styleElement.removeChild(childNodes[index]);
174 if (childNodes.length) {
175 styleElement.insertBefore(cssNode, childNodes[index]);
176 } else {
177 styleElement.appendChild(cssNode);
178 }
179 }
180}
181
182function applyToTag(styleElement, obj) {
183 var css = obj.css;
184 var media = obj.media;
185 var sourceMap = obj.sourceMap;
186
187 if(media) {
188 styleElement.setAttribute("media", media)
189 }
190
191 if(styleElement.styleSheet) {
192 styleElement.styleSheet.cssText = css;
193 } else {
194 while(styleElement.firstChild) {
195 styleElement.removeChild(styleElement.firstChild);
196 }
197 styleElement.appendChild(document.createTextNode(css));
198 }
199}
200
201function updateLink(linkElement, obj) {
202 var css = obj.css;
203 var media = obj.media;
204 var sourceMap = obj.sourceMap;
205
206 if(sourceMap) {
207 css += "\n/*# sourceMappingURL=data:application/json;base64," + btoa(JSON.stringify(sourceMap)) + " */";
208 }
209
210 var blob = new Blob([css], { type: "text/css" });
211
212 var oldSrc = linkElement.href;
213
214 linkElement.href = URL.createObjectURL(blob);
215
216 if(oldSrc)
217 URL.revokeObjectURL(oldSrc);
218}