UNPKG

isomorphic-style-loader

Version:

CSS style loader for Webpack optimized for critical path CSS rendering and isomoprhic web apps

105 lines (88 loc) 2.53 kB
/** * Isomorphic CSS style loader for Webpack * * Copyright © 2015-present Kriasoft, LLC. All rights reserved. * * This source code is licensed under the MIT license found in the * LICENSE.txt file in the root directory of this source tree. */ const inserted = {} // Base64 encoding and decoding - The "Unicode Problem" // https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem function b64EncodeUnicode(str) { return btoa( encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (match, p1) => String.fromCharCode(`0x${p1}`), ), ) } /** * Remove style/link elements for specified node IDs * if they are no longer referenced by UI components. */ function removeCss(ids) { ids.forEach((id) => { if (--inserted[id] <= 0) { const elem = document.getElementById(id) if (elem) { elem.parentNode.removeChild(elem) } } }) } /** * Example: * // Insert CSS styles object generated by `css-loader` into DOM * var removeCss = insertCss([[1, 'body { color: red; }']]); * * // Remove it from the DOM * removeCss(); */ function insertCss(styles, { replace = false, prepend = false, prefix = 's' } = {}) { const ids = [] for (let i = 0; i < styles.length; i++) { const [moduleId, css, media, sourceMap] = styles[i] const id = `${prefix}${moduleId}-${i}` ids.push(id) if (inserted[id]) { if (!replace) { inserted[id]++ continue } } inserted[id] = 1 let elem = document.getElementById(id) let create = false if (!elem) { create = true elem = document.createElement('style') elem.setAttribute('type', 'text/css') elem.id = id if (media) { elem.setAttribute('media', media) } } let cssText = css if (sourceMap && typeof btoa === 'function') { // skip IE9 and below, see http://caniuse.com/atob-btoa cssText += `\n/*# sourceMappingURL=data:application/json;base64,${b64EncodeUnicode( JSON.stringify(sourceMap), )}*/` cssText += `\n/*# sourceURL=${sourceMap.file}?${id}*/` } if ('textContent' in elem) { elem.textContent = cssText } else { elem.styleSheet.cssText = cssText } if (create) { if (prepend) { document.head.insertBefore(elem, document.head.childNodes[0]) } else { document.head.appendChild(elem) } } } return removeCss.bind(null, ids) } module.exports = insertCss