-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
94 lines (71 loc) · 2.99 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import React from 'react';
import { nanoid } from 'nanoid';
import ReactDOM from 'react-dom';
let __stylizerComponentRegistry = [];
let __stylizerGlobalRegistry = [];
export function parseComponentToStyle({ component, toClassName, shouldUnmount = true }) {
let parsedRules = '';
const styledRootId = `extract-emotion-styles-root-${nanoid(7)}`;
const styledElementId = `extract-emotion-styles-${nanoid(7)}`;
const styledRoot = document.createElement('div');
styledRoot.setAttribute('id', styledRootId);
document.body.appendChild(styledRoot);
ReactDOM.render(
<div style={{ display: 'none' }}>
{React.cloneElement(component, { id: styledElementId })}
</div>,
document.getElementById(styledRootId)
);
// We need to grab prototype methods themselves so that we can work on the static version of css selectors/query selectors.
const { filter } = Array.prototype;
const refClasses = document
.getElementById(styledElementId)
.className.split(' ')
refClasses.forEach((className) => {
// Add a dot so we can search the raw CSS selectorText.
const refClassName = `.${refClasses[0]}`;
const findSelectors = document.querySelectorAll('[data-emotion]');
const filteredRules = filter.call(findSelectors, (node) => node.innerText.includes(refClasses[0]));
if (toClassName) {
filteredRules.forEach((ruleSet) => {
parsedRules += `${ruleSet.innerText.replaceAll(refClassName, toClassName)} `;
});
} else {
filteredRules.forEach((ruleSet) => {
parsedRules += `${ruleSet.innerText} `;
});
}
})
if (shouldUnmount) {
ReactDOM.unmountComponentAtNode(document.getElementById(styledRootId))
document.body.removeChild(document.getElementById(styledRootId));
}
return parsedRules;
}
function reRender() {
if (document.querySelectorAll('style[data-extractor-stylizer]').length === 0) {
const stylesRoot = document.createElement('style');
stylesRoot.setAttribute('data-extractor-stylizer', 'true');
document.head.appendChild(stylesRoot);
}
let sheet = '';
__stylizerComponentRegistry.forEach((styleSet) => {
sheet += `${styleSet.styles} `;
});
__stylizerGlobalRegistry.forEach((textStyle) => {
sheet += `${textStyle} `;
});
ReactDOM.render(<>{sheet}</>, document.querySelectorAll('style[data-extractor-stylizer]')[0]);
}
export function applyComponentStylesToClass({ component, toClassName, shouldUnmount }) {
if (__stylizerComponentRegistry.find((x) => x.toClassName === toClassName)) {
return;
}
const styles = parseComponentToStyle({ component, toClassName, shouldUnmount });
__stylizerComponentRegistry.push({ toClassName, styles });
reRender();
}
export function addRawCssToGlobalStyles(rawCSS) {
__stylizerGlobalRegistry.push(rawCSS.replace(/ {2}|\r\n|\n|\r/gm, ' '));
reRender();
}