Skip to content

Commit 1dea229

Browse files
committed
Convert @emotion/cache's source code to TypeScript
1 parent c161e6f commit 1dea229

File tree

12 files changed

+161
-192
lines changed

12 files changed

+161
-192
lines changed

.changeset/fluffy-garlics-smash.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@emotion/cache': minor
3+
---
4+
5+
Source code has been migrated to TypeScript. From now on type declarations will be emitted based on that, instead of being hand-written.

packages/cache/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
"devDependencies": {
9191
"@definitelytyped/dtslint": "0.0.112",
9292
"@emotion/hash": "*",
93+
"@types/stylis": "^4.2.6",
9394
"typescript": "^5.4.5"
9495
},
9596
"files": [

packages/cache/src/index.d.ts

Lines changed: 0 additions & 2 deletions
This file was deleted.

packages/cache/src/index.js renamed to packages/cache/src/index.tsx

Lines changed: 36 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { StyleSheet } from '@emotion/sheet'
2-
/* import { type EmotionCache, type SerializedStyles } from '@emotion/utils' */
2+
import { type EmotionCache, type SerializedStyles } from '@emotion/utils'
33
import {
44
serialize,
55
compile,
66
middleware,
77
rulesheet,
88
stringify,
9-
COMMENT
9+
COMMENT,
10+
type Element as StylisElement
1011
} from 'stylis'
1112
import weakMemoize from '@emotion/weak-memoize'
1213
import memoize from '@emotion/memoize'
@@ -19,32 +20,26 @@ import {
1920
incorrectImportAlarm
2021
} from './stylis-plugins'
2122
import { prefixer } from './prefixer'
22-
/* import type { StylisPlugin } from './types' */
23+
import { StylisPlugin } from './types'
2324

24-
/*
25-
export type Options = {
26-
nonce?: string,
27-
stylisPlugins?: StylisPlugin[],
28-
key: string,
29-
container?: HTMLElement,
30-
speedy?: boolean,
31-
prepend?: boolean,
25+
export interface Options {
26+
nonce?: string
27+
stylisPlugins?: Array<StylisPlugin>
28+
key: string
29+
container?: Node
30+
speedy?: boolean
31+
/** @deprecate use `insertionPoint` instead */
32+
prepend?: boolean
3233
insertionPoint?: HTMLElement
3334
}
34-
*/
3535

3636
let getServerStylisCache = isBrowser
3737
? undefined
38-
: weakMemoize(() =>
39-
memoize(() => {
40-
let cache = {}
41-
return name => cache[name]
42-
})
43-
)
38+
: weakMemoize(() => memoize<Record<string, string>>(() => ({})))
4439

4540
const defaultStylisPlugins = [prefixer]
4641

47-
let getSourceMap
42+
let getSourceMap: ((styles: string) => string | undefined) | undefined
4843
if (isDevelopment) {
4944
let sourceMapPattern =
5045
/\/\*#\ssourceMappingURL=data:application\/json;\S+\s+\*\//g
@@ -55,7 +50,7 @@ if (isDevelopment) {
5550
}
5651
}
5752

58-
let createCache = (options /*: Options */) /*: EmotionCache */ => {
53+
let createCache = (options: Options): EmotionCache => {
5954
let key = options.key
6055

6156
if (isDevelopment && !key) {
@@ -100,18 +95,18 @@ let createCache = (options /*: Options */) /*: EmotionCache */ => {
10095
)
10196
}
10297
}
103-
let inserted = {}
104-
let container /* : Node */
105-
const nodesToHydrate = []
98+
let inserted: EmotionCache['inserted'] = {}
99+
let container: Node
100+
const nodesToHydrate: HTMLStyleElement[] = []
106101
if (isBrowser) {
107102
container = options.container || document.head
108103

109104
Array.prototype.forEach.call(
110105
// this means we will ignore elements which don't have a space in them which
111106
// means that the style elements we're looking at are only Emotion 11 server-rendered style elements
112107
document.querySelectorAll(`style[data-emotion^="${key} "]`),
113-
(node /*: HTMLStyleElement */) => {
114-
const attrib = node.getAttribute(`data-emotion`).split(' ')
108+
(node: HTMLStyleElement) => {
109+
const attrib = node.getAttribute(`data-emotion`)!.split(' ')
115110
for (let i = 1; i < attrib.length; i++) {
116111
inserted[attrib[i]] = true
117112
}
@@ -120,12 +115,12 @@ let createCache = (options /*: Options */) /*: EmotionCache */ => {
120115
)
121116
}
122117

123-
let insert /*: (
118+
let insert: (
124119
selector: string,
125120
serialized: SerializedStyles,
126121
sheet: StyleSheet,
127122
shouldCache: boolean
128-
) => string | void */
123+
) => string | void
129124
const omnipresentPlugins = [compat, removeLabel]
130125

131126
if (isDevelopment) {
@@ -139,13 +134,13 @@ let createCache = (options /*: Options */) /*: EmotionCache */ => {
139134
)
140135
}
141136

142-
if (isBrowser) {
143-
let currentSheet
137+
if (!getServerStylisCache) {
138+
let currentSheet: Pick<StyleSheet, 'insert'>
144139

145140
const finalizingPlugins = [
146141
stringify,
147142
isDevelopment
148-
? element => {
143+
? (element: StylisElement) => {
149144
if (!element.root) {
150145
if (element.return) {
151146
currentSheet.insert(element.return)
@@ -164,17 +159,12 @@ let createCache = (options /*: Options */) /*: EmotionCache */ => {
164159
const serializer = middleware(
165160
omnipresentPlugins.concat(stylisPlugins, finalizingPlugins)
166161
)
167-
const stylis = styles => serialize(compile(styles), serializer)
162+
const stylis = (styles: string) => serialize(compile(styles), serializer)
168163

169-
insert = (
170-
selector /*: string */,
171-
serialized /*: SerializedStyles */,
172-
sheet /*: StyleSheet */,
173-
shouldCache /*: boolean */
174-
) /*: void */ => {
164+
insert = (selector, serialized, sheet, shouldCache) => {
175165
currentSheet = sheet
176166

177-
if (isDevelopment) {
167+
if (getSourceMap) {
178168
let sourceMap = getSourceMap(serialized.styles)
179169
if (sourceMap) {
180170
currentSheet = {
@@ -196,13 +186,10 @@ let createCache = (options /*: Options */) /*: EmotionCache */ => {
196186
const serializer = middleware(
197187
omnipresentPlugins.concat(stylisPlugins, finalizingPlugins)
198188
)
199-
const stylis = styles => serialize(compile(styles), serializer)
189+
const stylis = (styles: string) => serialize(compile(styles), serializer)
200190

201191
let serverStylisCache = getServerStylisCache(stylisPlugins)(key)
202-
let getRules = (
203-
selector /*: string */,
204-
serialized /*: SerializedStyles */
205-
) /*: string */ => {
192+
let getRules = (selector: string, serialized: SerializedStyles): string => {
206193
let name = serialized.name
207194
if (serverStylisCache[name] === undefined) {
208195
serverStylisCache[name] = stylis(
@@ -211,12 +198,7 @@ let createCache = (options /*: Options */) /*: EmotionCache */ => {
211198
}
212199
return serverStylisCache[name]
213200
}
214-
insert = (
215-
selector /*: string */,
216-
serialized /*: SerializedStyles */,
217-
sheet /*: StyleSheet */,
218-
shouldCache /*: boolean */
219-
) /*: string | void */ => {
201+
insert = (selector, serialized, sheet, shouldCache) => {
220202
let name = serialized.name
221203
let rules = getRules(selector, serialized)
222204
if (cache.compat === undefined) {
@@ -226,7 +208,7 @@ let createCache = (options /*: Options */) /*: EmotionCache */ => {
226208
if (shouldCache) {
227209
cache.inserted[name] = true
228210
}
229-
if (isDevelopment) {
211+
if (getSourceMap) {
230212
let sourceMap = getSourceMap(serialized.styles)
231213
if (sourceMap) {
232214
return rules + sourceMap
@@ -251,11 +233,11 @@ let createCache = (options /*: Options */) /*: EmotionCache */ => {
251233
}
252234
}
253235

254-
const cache /*: EmotionCache */ = {
236+
const cache: EmotionCache = {
255237
key,
256238
sheet: new StyleSheet({
257239
key,
258-
container,
240+
container: container!,
259241
nonce: options.nonce,
260242
speedy: options.speedy,
261243
prepend: options.prepend,
@@ -273,3 +255,5 @@ let createCache = (options /*: Options */) /*: EmotionCache */ => {
273255
}
274256

275257
export default createCache
258+
export { EmotionCache }
259+
export type { StylisElement, StylisPlugin, StylisPluginCallback } from './types'

packages/cache/src/prefixer.js renamed to packages/cache/src/prefixer.tsx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import {
44
charat,
55
combine,
6-
copy,
6+
copy as _copy,
77
DECLARATION,
88
hash,
99
indexof,
@@ -15,12 +15,17 @@ import {
1515
RULESET,
1616
serialize,
1717
strlen,
18-
WEBKIT
18+
WEBKIT,
19+
type Element,
20+
Middleware
1921
} from 'stylis'
2022

23+
// `@types/stylis` are inaccurate, so we temporarily cast to our own definitions until fix lands: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/71310
24+
const copy: (root: Element, props: Partial<Element>) => Element = _copy as any
25+
2126
// this is a copy of [email protected] prefixer, the latter version introduced grid prefixing which we don't want
2227

23-
function prefix(value, length) {
28+
function prefix(value: string, length: number): string {
2429
switch (hash(value, length)) {
2530
// color-adjust
2631
case 5103:
@@ -279,7 +284,12 @@ function prefix(value, length) {
279284
return value
280285
}
281286

282-
export let prefixer = (element, index, children, callback) => {
287+
export let prefixer = (
288+
element: Element,
289+
index: number,
290+
children: Element[],
291+
callback: Middleware
292+
) => {
283293
if (element.length > -1)
284294
if (!element.return)
285295
switch (element.type) {
@@ -297,7 +307,7 @@ export let prefixer = (element, index, children, callback) => {
297307
)
298308
case RULESET:
299309
if (element.length)
300-
return combine(element.props, function (value) {
310+
return combine(element.props as string[], function (value) {
301311
switch (match(value, /(::plac\w+|:read-\w+)/)) {
302312
// :read-(only|write)
303313
case ':read-only':

0 commit comments

Comments
 (0)