2014-09-08 00:23:54 +04:00
|
|
|
/*
|
|
|
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
|
|
|
Author Tobias Koppers @sokra
|
|
|
|
*/
|
2014-10-20 20:22:46 +04:00
|
|
|
var stylesInDom = {},
|
|
|
|
memoize = function(fn) {
|
|
|
|
var memo;
|
|
|
|
return function () {
|
|
|
|
if (typeof memo === "undefined") memo = fn.apply(this, arguments);
|
|
|
|
return memo;
|
|
|
|
};
|
|
|
|
},
|
|
|
|
isIE9 = memoize(function() {
|
|
|
|
return /msie 9\b/.test(window.navigator.userAgent.toLowerCase());
|
|
|
|
}),
|
|
|
|
getHeadElement = memoize(function () {
|
|
|
|
return document.head || document.getElementsByTagName("head")[0];
|
|
|
|
}),
|
2014-10-21 13:36:13 +04:00
|
|
|
singletonElement = null,
|
|
|
|
singletonCounter = 0;
|
2014-09-08 00:23:54 +04:00
|
|
|
|
2014-10-20 20:22:46 +04:00
|
|
|
module.exports = function(list, options) {
|
2014-09-08 00:23:54 +04:00
|
|
|
if(typeof DEBUG !== "undefined" && DEBUG) {
|
|
|
|
if(typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment");
|
|
|
|
}
|
2014-10-21 13:36:13 +04:00
|
|
|
|
2014-10-20 20:22:46 +04:00
|
|
|
options = options || {};
|
|
|
|
// Force single-tag solution on IE9, which has a hard limit on the # of <style>
|
|
|
|
// tags it will allow on a page
|
2014-10-21 13:36:13 +04:00
|
|
|
if (typeof options.singleton === "undefined") options.singleton = isIE9();
|
|
|
|
|
|
|
|
var styles = listToStyles(list);
|
2014-10-20 20:22:46 +04:00
|
|
|
addStylesToDom(styles, options);
|
2014-10-21 13:36:13 +04:00
|
|
|
|
2014-09-08 00:23:54 +04:00
|
|
|
return function update(newList) {
|
|
|
|
var mayRemove = [];
|
|
|
|
for(var i = 0; i < styles.length; i++) {
|
|
|
|
var item = styles[i];
|
|
|
|
var domStyle = stylesInDom[item.id];
|
|
|
|
domStyle.refs--;
|
|
|
|
mayRemove.push(domStyle);
|
|
|
|
}
|
|
|
|
if(newList) {
|
|
|
|
var newStyles = listToStyles(newList);
|
2014-10-20 20:22:46 +04:00
|
|
|
addStylesToDom(newStyles, options);
|
2014-09-08 00:23:54 +04:00
|
|
|
}
|
|
|
|
for(var i = 0; i < mayRemove.length; i++) {
|
|
|
|
var domStyle = mayRemove[i];
|
|
|
|
if(domStyle.refs === 0) {
|
|
|
|
for(var j = 0; j < domStyle.parts.length; j++)
|
|
|
|
domStyle.parts[j]();
|
|
|
|
delete stylesInDom[domStyle.id];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2014-10-20 20:22:46 +04:00
|
|
|
function addStylesToDom(styles, options) {
|
2014-09-08 00:23:54 +04:00
|
|
|
for(var i = 0; i < styles.length; i++) {
|
|
|
|
var item = styles[i];
|
|
|
|
var domStyle = stylesInDom[item.id];
|
|
|
|
if(domStyle) {
|
|
|
|
domStyle.refs++;
|
|
|
|
for(var j = 0; j < domStyle.parts.length; j++) {
|
|
|
|
domStyle.parts[j](item.parts[j]);
|
|
|
|
}
|
|
|
|
for(; j < item.parts.length; j++) {
|
2014-10-20 20:22:46 +04:00
|
|
|
domStyle.parts.push(addStyle(item.parts[j], options));
|
2014-09-08 00:23:54 +04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
var parts = [];
|
|
|
|
for(var j = 0; j < item.parts.length; j++) {
|
2014-10-20 20:22:46 +04:00
|
|
|
parts.push(addStyle(item.parts[j], options));
|
2014-09-08 00:23:54 +04:00
|
|
|
}
|
|
|
|
stylesInDom[item.id] = {id: item.id, refs: 1, parts: parts};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function listToStyles(list) {
|
|
|
|
var styles = [];
|
|
|
|
var newStyles = {};
|
|
|
|
for(var i = 0; i < list.length; i++) {
|
|
|
|
var item = list[i];
|
|
|
|
var id = item[0];
|
|
|
|
var css = item[1];
|
|
|
|
var media = item[2];
|
|
|
|
// var sourceMap = item[3];
|
|
|
|
var part = {css: css, media: media/*, sourceMap: sourceMap*/};
|
|
|
|
if(!newStyles[id])
|
|
|
|
styles.push(newStyles[id] = {id: id, parts: [part]});
|
|
|
|
else
|
|
|
|
newStyles[id].parts.push(part);
|
|
|
|
}
|
|
|
|
return styles;
|
|
|
|
}
|
|
|
|
|
2014-10-20 20:22:46 +04:00
|
|
|
function createStyleElement() {
|
2014-09-08 00:23:54 +04:00
|
|
|
var styleElement = document.createElement("style");
|
2014-10-20 20:22:46 +04:00
|
|
|
var head = getHeadElement();
|
2014-09-08 00:23:54 +04:00
|
|
|
styleElement.type = "text/css";
|
|
|
|
head.appendChild(styleElement);
|
2014-10-20 20:22:46 +04:00
|
|
|
return styleElement;
|
|
|
|
}
|
|
|
|
|
|
|
|
function addStyle(obj, options) {
|
2014-10-21 13:36:13 +04:00
|
|
|
var styleElement, update, remove;
|
|
|
|
|
|
|
|
if (options.singleton) {
|
|
|
|
var styleIndex = singletonCounter++;
|
|
|
|
styleElement = singletonElement || (singletonElement = createStyleElement());
|
|
|
|
update = applyToSingletonTag.bind(null, styleElement, styleIndex, false);
|
|
|
|
remove = applyToSingletonTag.bind(null, styleElement, styleIndex, true);
|
2014-10-20 20:22:46 +04:00
|
|
|
} else {
|
|
|
|
styleElement = createStyleElement();
|
2014-10-21 13:36:13 +04:00
|
|
|
update = applyToTag.bind(null, styleElement);
|
|
|
|
remove = function () {
|
|
|
|
styleElement.parentNode.removeChild(styleElement);
|
|
|
|
};
|
2014-10-20 20:22:46 +04:00
|
|
|
}
|
|
|
|
|
2014-10-21 13:36:13 +04:00
|
|
|
update(obj);
|
2014-10-20 20:22:46 +04:00
|
|
|
|
2014-10-21 13:36:13 +04:00
|
|
|
return function updateStyle(newObj) {
|
2014-09-08 00:23:54 +04:00
|
|
|
if(newObj) {
|
|
|
|
if(newObj.css === obj.css && newObj.media === obj.media /*&& newObj.sourceMap === obj.sourceMap*/)
|
|
|
|
return;
|
2014-10-21 13:36:13 +04:00
|
|
|
update(obj = newObj);
|
2014-09-08 00:23:54 +04:00
|
|
|
} else {
|
2014-10-21 13:36:13 +04:00
|
|
|
remove();
|
2014-09-08 00:23:54 +04:00
|
|
|
}
|
|
|
|
};
|
2014-10-21 13:36:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
function replaceText(source, id, replacement) {
|
|
|
|
var boundaries = ['/** >>' + id + ' **/', '/** ' + id + '<< **/'];
|
|
|
|
var start = source.lastIndexOf(boundaries[0]);
|
|
|
|
var wrappedReplacement = boundaries[0] + replacement + boundaries[1];
|
|
|
|
if (source.lastIndexOf(boundaries[0]) >= 0) {
|
|
|
|
var end = source.lastIndexOf(boundaries[1]) + boundaries[1].length;
|
|
|
|
return source.slice(0, start) + wrappedReplacement + source.slice(end);
|
|
|
|
} else {
|
|
|
|
return source + wrappedReplacement;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function applyToSingletonTag(styleElement, index, remove, obj) {
|
|
|
|
var css = remove ? '' : obj.css;
|
|
|
|
|
|
|
|
if(styleElement.styleSheet) {
|
|
|
|
styleElement.styleSheet.cssText = replaceText(styleElement.styleSheet.cssText, index, css);
|
|
|
|
} else {
|
|
|
|
var cssNode = document.createTextNode(css);
|
|
|
|
var childNodes = styleElement.childNodes;
|
|
|
|
if (childNodes[index]) styleElement.removeChild(childNodes[index]);
|
|
|
|
if (childNodes.length) {
|
|
|
|
styleElement.insertBefore(cssNode, childNodes[index]);
|
|
|
|
} else {
|
|
|
|
styleElement.appendChild(cssNode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-09-08 00:23:54 +04:00
|
|
|
|
|
|
|
function applyToTag(styleElement, obj) {
|
|
|
|
var css = obj.css;
|
|
|
|
var media = obj.media;
|
|
|
|
// var sourceMap = obj.sourceMap;
|
|
|
|
// No browser support
|
|
|
|
// if(sourceMap && typeof btoa === "function") {
|
|
|
|
// try {
|
|
|
|
// css += "\n/*# sourceMappingURL=data:application/json;base64," + btoa(JSON.stringify(sourceMap)) + " */";
|
|
|
|
// } catch(e) {}
|
|
|
|
// }
|
2014-10-20 20:22:46 +04:00
|
|
|
|
2014-09-08 00:23:54 +04:00
|
|
|
if(media) {
|
|
|
|
styleElement.setAttribute("media", media)
|
|
|
|
}
|
2014-10-20 20:22:46 +04:00
|
|
|
|
|
|
|
if(styleElement.styleSheet) {
|
2014-10-21 13:36:13 +04:00
|
|
|
styleElement.styleSheet.cssText = css;
|
2014-09-08 00:23:54 +04:00
|
|
|
} else {
|
2014-10-21 13:36:13 +04:00
|
|
|
while(styleElement.firstChild) {
|
|
|
|
styleElement.removeChild(styleElement.firstChild);
|
2014-09-08 00:23:54 +04:00
|
|
|
}
|
2014-10-21 13:36:13 +04:00
|
|
|
styleElement.appendChild(cssNode);
|
2014-09-08 00:23:54 +04:00
|
|
|
}
|
|
|
|
}
|