index.js
3.08 KB
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// @flow
import { StyleSheet } from '@emotion/sheet'
import { isBrowser, type CSSContextType } from '@emotion/utils'
import Stylis from '@emotion/stylis'
import ruleSheetPlugin from './rule-sheet'
import type { StylisPlugin } from './types'
export type PrefixOption =
| boolean
| ((key: string, value: string, context: 1 | 2 | 3) => boolean)
type StylisPlugins = StylisPlugin[] | StylisPlugin
export type Options = {
nonce?: string,
stylisPlugins?: StylisPlugins,
prefix?: PrefixOption,
key?: string,
container?: HTMLElement
}
let createCache = (options?: Options): CSSContextType => {
if (options === undefined) options = {}
let key = options.key || 'css'
let stylisOptions
if (options.prefix !== undefined) {
stylisOptions = {
prefix: options.prefix
}
}
let stylis = new Stylis(stylisOptions)
stylis.use(options.stylisPlugins)(ruleSheetPlugin)
if (process.env.NODE_ENV !== 'production') {
// $FlowFixMe
if (/[^a-z-]/.test(key)) {
throw new Error(
`Emotion key must only contain lower case alphabetical characters and - but "${key}" was passed`
)
}
let sourceMapRegEx = /\/\*#\ssourceMappingURL=data:application\/json;\S+\s+\*\//
let currentSourceMap
stylis.use((context, content, selectors) => {
switch (context) {
case -1: {
let result = sourceMapRegEx.exec(content)
if (result) {
currentSourceMap = result[0]
}
break
}
case 2: {
for (let i = 0, len = selectors.length; len > i; i++) {
// :last-child isn't included here since it's safe
// because a style element will never be the last element
let match = selectors[i].match(/:(first|nth|nth-last)-child/)
if (match !== null) {
console.error(
`The pseudo class "${
match[1]
}" is potentially unsafe when doing server-side rendering. Try changing it to "${
match[1]
}-of-type"`
)
}
}
break
}
case -2: {
if (currentSourceMap) {
content.forEach((rule, i) => {
content[i] = rule + currentSourceMap
})
currentSourceMap = ''
}
}
}
})
}
let inserted = {}
// $FlowFixMe
let container: HTMLElement
if (isBrowser) {
container = options.container || document.head
const nodes = document.querySelectorAll(`style[data-emotion-${key}]`)
Array.prototype.forEach.call(nodes, (node: HTMLStyleElement) => {
const attrib = node.getAttribute(`data-emotion-${key}`)
// $FlowFixMe
attrib.split(' ').forEach(id => {
inserted[id] = true
})
if (node.parentNode !== container) {
container.appendChild(node)
}
})
}
const context: CSSContextType = {
stylis,
key,
sheet: new StyleSheet({
key,
container,
nonce: options.nonce
}),
inserted,
registered: {},
theme: {}
}
return context
}
export default createCache