UNPKG

isomorphic-style-loader

Version:

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

108 lines (92 loc) 2.6 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. */ import createUniqueIdentifiers from './createUniqueIdentifiers' const inserted = Object.create(null) // 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(parseInt(p1, 16)), ), ) } /** * 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) { delete inserted[id] 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 = [] const identifiers = createUniqueIdentifiers(styles.map(([moduleId]) => moduleId)) for (let i = 0; i < styles.length; i++) { const [, css, media, sourceMap] = styles[i] const id = `${prefix}${identifiers[i]}` if (inserted[id]) { if (!replace) { inserted[id]++ ids.push(id) continue } } else { inserted[id] = 1 ids.push(id) } let elem = document.getElementById(id) let create = false if (!elem) { create = true elem = document.createElement('style') elem.id = id if (media) { elem.setAttribute('media', media) } } let cssText = css if (sourceMap) { cssText += `\n/*# sourceMappingURL=data:application/json;base64,${b64EncodeUnicode( JSON.stringify(sourceMap), )}*/` cssText += `\n/*# sourceURL=${sourceMap.file}?${id}*/` } elem.textContent = cssText if (create) { if (prepend) { document.head.insertBefore(elem, document.head.childNodes[0]) } else { document.head.appendChild(elem) } } } let removed = false return () => { if (removed) return removed = true removeCss(ids) } } export default insertCss