Created
November 14, 2018 01:46
-
-
Save whs/32cca87838ab5071bb9e0c01672ce95f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import {caches as defaultCaches} from 'emotion'; | |
| import parse5 from 'parse5'; | |
| import { | |
| insertBefore, | |
| createElement, | |
| insertText, | |
| createDocumentFragment, | |
| appendChild, | |
| } from 'parse5/lib/tree-adapters/default'; | |
| function generateStyleTag(cssKey, ids, styles) { | |
| let out = createElement('style', '', [ | |
| { | |
| name: `data-emotion-${cssKey}`, | |
| value: ids.join(' '), | |
| }, | |
| ]); | |
| insertText(out, styles); | |
| return out; | |
| } | |
| function findAttr(attrs, key) { | |
| for (let item of attrs) { | |
| if (item.name === key) { | |
| return item; | |
| } | |
| } | |
| return null; | |
| } | |
| function renderStyleToString(caches, html) { | |
| // generate global style | |
| let globalStyle = ''; | |
| let globalIds = []; | |
| let seen = {}; | |
| for (let id of Object.keys(caches.inserted)) { | |
| let style = caches.inserted[id]; | |
| if ( | |
| style !== true && | |
| caches.registered[`${caches.key}-${id}`] === undefined | |
| ) { | |
| globalStyle += style; | |
| globalIds.push(id); | |
| seen[id] = true; | |
| } | |
| } | |
| // parse html and find used stylesheet | |
| let document = parse5.parseFragment(html); | |
| const walk = node => { | |
| if (node.attrs) { | |
| let clsAttr = findAttr(node.attrs, 'class'); | |
| if (clsAttr) { | |
| let classes = clsAttr.value.split(' '); | |
| let localIds = []; | |
| let localStyle = ''; | |
| for (let cls of classes) { | |
| let rawId = cls.substring(caches.key.length + 1); | |
| if (!seen[rawId] && caches.registered[cls] !== undefined) { | |
| seen[rawId] = true; | |
| localIds.push(rawId); | |
| let style = caches.inserted[rawId]; | |
| if (style !== true) { | |
| localStyle += style; | |
| } | |
| } | |
| } | |
| if (localStyle) { | |
| let styleNode = generateStyleTag(caches.key, localIds, localStyle); | |
| insertBefore(node.parentNode, styleNode, node); | |
| } | |
| } | |
| } | |
| if (node.childNodes) { | |
| for (let child of node.childNodes) { | |
| walk(child); | |
| } | |
| } | |
| }; | |
| walk(document); | |
| html = parse5.serialize(document); | |
| // prepend global styles | |
| if (globalStyle) { | |
| let fragment = createDocumentFragment(); | |
| appendChild(fragment, generateStyleTag(caches.key, globalIds, globalStyle)); | |
| html = parse5.serialize(fragment) + html; | |
| } | |
| return html; | |
| } | |
| export default html => renderStyleToString(defaultCaches, html); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment