;"
`;
exports[`@emotion/babel-plugin object-property 1`] = `
-"// @flow
-import * as React from 'react'
+"import * as React from 'react'
import { jsx } from '@emotion/react'
import styled from '@emotion/styled'
@@ -323,7 +318,6 @@ import _styled from "@emotion/styled/base";
function _EMOTION_STRINGIFIED_CSS_ERROR__() { return "You have tried to stringify object returned from \`css\` function. It isn't supposed to be used directly (e.g. as value of the \`className\` prop), but rather handed to emotion so it can handle it (e.g. as value of \`css\` prop)."; }
-// @flow
import * as React from 'react';
import { jsx } from '@emotion/react';
const MyObject = {
@@ -338,7 +332,7 @@ const MyObject = {
} : {
name: "3sn2xs",
styles: "color:hotpink",
- map: "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm9iamVjdC1wcm9wZXJ0eS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFNYyIsImZpbGUiOiJvYmplY3QtcHJvcGVydHkuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAZmxvd1xuaW1wb3J0ICogYXMgUmVhY3QgZnJvbSAncmVhY3QnXG5pbXBvcnQgeyBqc3ggfSBmcm9tICdAZW1vdGlvbi9yZWFjdCdcbmltcG9ydCBzdHlsZWQgZnJvbSAnQGVtb3Rpb24vc3R5bGVkJ1xuXG5jb25zdCBNeU9iamVjdCA9IHtcbiAgTXlQcm9wZXJ0eTogc3R5bGVkLmRpdih7IGNvbG9yOiAnaG90cGluaycgfSlcbn1cblxuZnVuY3Rpb24gTG9nbyhwcm9wcykge1xuICByZXR1cm4gPE15T2JqZWN0Lk15UHJvcGVydHkgLz5cbn1cbiJdfQ== */",
+ map: "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm9iamVjdC1wcm9wZXJ0eS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFLYyIsImZpbGUiOiJvYmplY3QtcHJvcGVydHkuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IGpzeCB9IGZyb20gJ0BlbW90aW9uL3JlYWN0J1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5cbmNvbnN0IE15T2JqZWN0ID0ge1xuICBNeVByb3BlcnR5OiBzdHlsZWQuZGl2KHsgY29sb3I6ICdob3RwaW5rJyB9KVxufVxuXG5mdW5jdGlvbiBMb2dvKHByb3BzKSB7XG4gIHJldHVybiA8TXlPYmplY3QuTXlQcm9wZXJ0eSAvPlxufVxuIl19 */",
toString: _EMOTION_STRINGIFIED_CSS_ERROR__
})
};
diff --git a/packages/babel-plugin/__tests__/css-macro/index.js b/packages/babel-plugin/__tests__/css-macro/index.js
index fae1b1815f..4d73fb4e84 100644
--- a/packages/babel-plugin/__tests__/css-macro/index.js
+++ b/packages/babel-plugin/__tests__/css-macro/index.js
@@ -1,4 +1,3 @@
-// @flow
import babelTester from 'babel-tester'
babelTester('@emotion/react - css macro', __dirname)
diff --git a/packages/babel-plugin/__tests__/css-requires-options.js b/packages/babel-plugin/__tests__/css-requires-options.js
index fd91b0c079..9173c489df 100644
--- a/packages/babel-plugin/__tests__/css-requires-options.js
+++ b/packages/babel-plugin/__tests__/css-requires-options.js
@@ -1,4 +1,3 @@
-// @flow
import nodePath from 'path'
import babelTester from 'babel-tester'
import plugin from '@emotion/babel-plugin'
diff --git a/packages/babel-plugin/__tests__/global-macro/index.js b/packages/babel-plugin/__tests__/global-macro/index.js
index f2d2067288..c3eb1874e2 100644
--- a/packages/babel-plugin/__tests__/global-macro/index.js
+++ b/packages/babel-plugin/__tests__/global-macro/index.js
@@ -1,4 +1,3 @@
-// @flow
import babelTester from 'babel-tester'
babelTester('@emotion/react - Global macro', __dirname)
diff --git a/packages/babel-plugin/__tests__/global-requires-options.js b/packages/babel-plugin/__tests__/global-requires-options.js
index e8e7cf1324..a8cd7cfad1 100644
--- a/packages/babel-plugin/__tests__/global-requires-options.js
+++ b/packages/babel-plugin/__tests__/global-requires-options.js
@@ -1,4 +1,3 @@
-// @flow
import babelTester from 'babel-tester'
import plugin from '@emotion/babel-plugin'
diff --git a/packages/babel-plugin/__tests__/styled-macro/index.js b/packages/babel-plugin/__tests__/styled-macro/index.js
index f183501efa..26c27d241d 100644
--- a/packages/babel-plugin/__tests__/styled-macro/index.js
+++ b/packages/babel-plugin/__tests__/styled-macro/index.js
@@ -1,4 +1,3 @@
-// @flow
import babelTester from 'babel-tester'
babelTester('@emotion/styled.macro', __dirname)
diff --git a/packages/babel-plugin/__tests__/styled-requires-options.js b/packages/babel-plugin/__tests__/styled-requires-options.js
index a2d1a57e26..05e003fb36 100644
--- a/packages/babel-plugin/__tests__/styled-requires-options.js
+++ b/packages/babel-plugin/__tests__/styled-requires-options.js
@@ -1,4 +1,3 @@
-// @flow
import babelTester from 'babel-tester'
import plugin from '@emotion/babel-plugin'
diff --git a/packages/babel-plugin/__tests__/vanilla-emotion-macro/index.js b/packages/babel-plugin/__tests__/vanilla-emotion-macro/index.js
index 07961ee8fe..cdce44dffd 100644
--- a/packages/babel-plugin/__tests__/vanilla-emotion-macro/index.js
+++ b/packages/babel-plugin/__tests__/vanilla-emotion-macro/index.js
@@ -1,4 +1,3 @@
-// @flow
import babelTester from 'babel-tester'
babelTester('vanilla emotion', __dirname)
diff --git a/packages/babel-plugin/src/core-macro.js b/packages/babel-plugin/src/core-macro.js
index 77f39f1244..c7f8c76961 100644
--- a/packages/babel-plugin/src/core-macro.js
+++ b/packages/babel-plugin/src/core-macro.js
@@ -1,4 +1,3 @@
-// @flow
import {
transformExpressionWithStyles,
createTransformerMacro,
@@ -6,19 +5,15 @@ import {
addImport
} from './utils'
-export const transformCssCallExpression = ({
- state,
- babel,
- path,
- sourceMap,
- annotateAsPure = true
-}: {
+export const transformCssCallExpression = (
+ { state, babel, path, sourceMap, annotateAsPure = true } /*: {
state: *,
babel: *,
path: *,
sourceMap?: string,
annotateAsPure?: boolean
-}) => {
+} */
+) => {
let node = transformExpressionWithStyles({
babel,
state,
@@ -34,15 +29,13 @@ export const transformCssCallExpression = ({
}
}
-export const transformCsslessArrayExpression = ({
- state,
- babel,
- path
-}: {
+export const transformCsslessArrayExpression = (
+ { state, babel, path } /*: {
babel: *,
state: *,
path: *
-}) => {
+} */
+) => {
let t = babel.types
let expressionPath = path.get('value.expression')
let sourceMap =
@@ -72,17 +65,14 @@ export const transformCsslessArrayExpression = ({
}
}
-export const transformCsslessObjectExpression = ({
- state,
- babel,
- path,
- cssImport
-}: {
+export const transformCsslessObjectExpression = (
+ { state, babel, path, cssImport } /*: {
babel: *,
state: *,
path: *,
cssImport: { importSource: string, cssExport: string }
-}) => {
+} */
+) => {
let t = babel.types
let expressionPath = path.get('value.expression')
let sourceMap =
@@ -115,31 +105,25 @@ export const transformCsslessObjectExpression = ({
}
}
-let cssTransformer = ({
- state,
- babel,
- reference
-}: {
+let cssTransformer = (
+ { state, babel, reference } /*: {
state: any,
babel: any,
reference: any
-}) => {
+} */
+) => {
transformCssCallExpression({ babel, state, path: reference.parentPath })
}
-let globalTransformer = ({
- state,
- babel,
- reference,
- importSource,
- options
-}: {
+let globalTransformer = (
+ { state, babel, reference, importSource, options } /*: {
state: any,
babel: any,
reference: any,
importSource: string,
options: { cssExport?: string }
-}) => {
+} */
+) => {
const t = babel.types
if (
diff --git a/packages/babel-plugin/src/emotion-macro.js b/packages/babel-plugin/src/emotion-macro.js
index 96b5954a67..67bf2c8e13 100644
--- a/packages/babel-plugin/src/emotion-macro.js
+++ b/packages/babel-plugin/src/emotion-macro.js
@@ -1,4 +1,3 @@
-// @flow
import { transformExpressionWithStyles, createTransformerMacro } from './utils'
const isAlreadyTranspiled = path => {
@@ -30,8 +29,10 @@ const isAlreadyTranspiled = path => {
}
let createEmotionTransformer =
- (isPure: boolean) =>
- ({ state, babel, importSource, reference, importSpecifierName }: Object) => {
+ (isPure /*: boolean */) =>
+ (
+ { state, babel, importSource, reference, importSpecifierName } /*: Object */
+ ) => {
const path = reference.parentPath
if (isAlreadyTranspiled(path)) {
@@ -59,5 +60,5 @@ export let transformers = {
keyframes: createEmotionTransformer(true)
}
-export let createEmotionMacro = (importSource: string) =>
+export let createEmotionMacro = (importSource /*: string */) =>
createTransformerMacro(transformers, { importSource })
diff --git a/packages/babel-plugin/src/index.js b/packages/babel-plugin/src/index.js
index 95731cd432..74f889c391 100644
--- a/packages/babel-plugin/src/index.js
+++ b/packages/babel-plugin/src/index.js
@@ -1,4 +1,3 @@
-// @flow
import {
createEmotionMacro,
transformers as vanillaTransformers
@@ -68,13 +67,15 @@ export const macros = {
vanillaEmotion: vanillaEmotionMacro
}
+/*
export type BabelPath = any
export type EmotionBabelPluginPass = any
+*/
const AUTO_LABEL_VALUES = ['dev-only', 'never', 'always']
-export default function (babel: *, options: *) {
+export default function (babel, options) {
if (
options.autoLabel !== undefined &&
!AUTO_LABEL_VALUES.includes(options.autoLabel)
@@ -90,7 +91,7 @@ export default function (babel: *, options: *) {
return {
name: '@emotion',
// https://github.com/babel/babel/blob/0c97749e0fe8ad845b902e0b23a24b308b0bf05d/packages/babel-plugin-syntax-jsx/src/index.ts#L9-L18
- manipulateOptions(opts: *, parserOpts: *) {
+ manipulateOptions(opts, parserOpts) {
const { plugins } = parserOpts
if (
@@ -105,7 +106,7 @@ export default function (babel: *, options: *) {
plugins.push('jsx')
},
visitor: {
- ImportDeclaration(path: *, state: *) {
+ ImportDeclaration(path, state) {
const macro = state.pluginMacros[path.node.source.value]
// most of this is from https://github.com/kentcdodds/babel-plugin-macros/blob/main/src/index.js
if (macro === undefined) {
@@ -159,13 +160,13 @@ export default function (babel: *, options: *) {
isBabelMacrosCall: true
})
},
- Program(path: *, state: *) {
+ Program(path, state) {
let macros = {}
- let jsxReactImports: Array<{
+ let jsxReactImports /*: Array<{
importSource: string,
export: string,
cssExport: string
- }> = [
+ }> */ = [
{ importSource: '@emotion/react', export: 'jsx', cssExport: 'css' }
]
state.jsxReactImport = jsxReactImports[0]
@@ -209,11 +210,11 @@ export default function (babel: *, options: *) {
}
}
- let [exportTransformer, defaultOptions] =
- // $FlowFixMe
- Array.isArray(packageTransformers[exportName])
- ? packageTransformers[exportName]
- : [packageTransformers[exportName]]
+ let [exportTransformer, defaultOptions] = Array.isArray(
+ packageTransformers[exportName]
+ )
+ ? packageTransformers[exportName]
+ : [packageTransformers[exportName]]
transformers[localExportName] = [
exportTransformer,
@@ -266,7 +267,7 @@ export default function (babel: *, options: *) {
state.emotionSourceMap = true
}
},
- JSXAttribute(path: *, state: *) {
+ JSXAttribute(path, state) {
if (path.node.name.name !== 'css' || !state.transformCssProp) {
return
}
@@ -289,7 +290,7 @@ export default function (babel: *, options: *) {
}
},
CallExpression: {
- exit(path: BabelPath, state: EmotionBabelPluginPass) {
+ exit(path /*: BabelPath */, state /*: EmotionBabelPluginPass */) {
try {
if (
path.node.callee &&
diff --git a/packages/babel-plugin/src/styled-macro.js b/packages/babel-plugin/src/styled-macro.js
index 1ccde3726c..5f4094fc65 100644
--- a/packages/babel-plugin/src/styled-macro.js
+++ b/packages/babel-plugin/src/styled-macro.js
@@ -1,4 +1,3 @@
-// @flow
import {
transformExpressionWithStyles,
getStyledOptions,
@@ -13,15 +12,16 @@ const getReferencedSpecifier = (path, specifierName) => {
: specifiers.find(p => p.node.local.name === specifierName)
}
-export let styledTransformer = ({
- state,
- babel,
- path,
- importSource,
- reference,
- importSpecifierName,
- options: { styledBaseImport, isWeb }
-}: {
+export let styledTransformer = (
+ {
+ state,
+ babel,
+ path,
+ importSource,
+ reference,
+ importSpecifierName,
+ options: { styledBaseImport, isWeb }
+ } /*: {
state: Object,
babel: Object,
path: any,
@@ -29,7 +29,8 @@ export let styledTransformer = ({
importSpecifierName: string,
reference: Object,
options: { styledBaseImport?: [string, string], isWeb: boolean }
-}) => {
+} */
+) => {
let t = babel.types
let getStyledIdentifier = () => {
@@ -119,17 +120,19 @@ export let styledTransformer = ({
}
}
-export let createStyledMacro = ({
- importSource,
- originalImportSource = importSource,
- baseImportName = 'default',
- isWeb
-}: {
+export let createStyledMacro = (
+ {
+ importSource,
+ originalImportSource = importSource,
+ baseImportName = 'default',
+ isWeb
+ } /*: {
importSource: string,
originalImportSource?: string,
baseImportName?: string,
isWeb: boolean
-}) =>
+} */
+) =>
createTransformerMacro(
{
default: [
diff --git a/packages/babel-plugin/src/utils/add-import.js b/packages/babel-plugin/src/utils/add-import.js
index 4d1113ac87..393ef1fb5f 100644
--- a/packages/babel-plugin/src/utils/add-import.js
+++ b/packages/babel-plugin/src/utils/add-import.js
@@ -1,10 +1,10 @@
import { addDefault, addNamed } from '@babel/helper-module-imports'
export function addImport(
- state: any,
- importSource: string,
- importedSpecifier: string,
- nameHint?: string
+ state,
+ importSource /*: string */,
+ importedSpecifier /*: string */,
+ nameHint /* ?: string */
) {
let cacheKey = ['import', importSource, importedSpecifier].join(':')
if (state[cacheKey] === undefined) {
diff --git a/packages/babel-plugin/src/utils/get-styled-options.js b/packages/babel-plugin/src/utils/get-styled-options.js
index b37b027f28..351afad60e 100644
--- a/packages/babel-plugin/src/utils/get-styled-options.js
+++ b/packages/babel-plugin/src/utils/get-styled-options.js
@@ -1,9 +1,8 @@
-// @flow
import { getLabelFromPath } from './label'
import { getTargetClassName } from './get-target-class-name'
import createNodeEnvConditional from './create-node-env-conditional'
-const getKnownProperties = (t: *, node: *) =>
+const getKnownProperties = (t, node) =>
new Set(
node.properties
.filter(n => t.isObjectProperty(n) && !n.computed)
@@ -13,7 +12,7 @@ const getKnownProperties = (t: *, node: *) =>
const createObjectSpreadLike = (t, file, ...objs) =>
t.callExpression(file.addHelper('extends'), [t.objectExpression([]), ...objs])
-export let getStyledOptions = (t: *, path: *, state: *) => {
+export let getStyledOptions = (t, path, state) => {
const autoLabel = state.opts.autoLabel || 'dev-only'
let args = path.node.arguments
diff --git a/packages/babel-plugin/src/utils/get-target-class-name.js b/packages/babel-plugin/src/utils/get-target-class-name.js
index 9b78a9725c..5d524b9206 100644
--- a/packages/babel-plugin/src/utils/get-target-class-name.js
+++ b/packages/babel-plugin/src/utils/get-target-class-name.js
@@ -1,11 +1,10 @@
-// @flow
import findRoot from 'find-root'
import memoize from '@emotion/memoize'
import nodePath from 'path'
import hashString from '@emotion/hash'
import escapeRegexp from 'escape-string-regexp'
-let hashArray = (arr: Array
) => hashString(arr.join(''))
+let hashArray = (arr /*: Array */) => hashString(arr.join(''))
const unsafeRequire = require
@@ -15,7 +14,7 @@ const separator = new RegExp(escapeRegexp(nodePath.sep), 'g')
const normalizePath = path => nodePath.normalize(path).replace(separator, '/')
-export function getTargetClassName(state: *, t: *) {
+export function getTargetClassName(state, t) {
if (state.emotionTargetClassNameCount === undefined) {
state.emotionTargetClassNameCount = 0
}
diff --git a/packages/babel-plugin/src/utils/index.js b/packages/babel-plugin/src/utils/index.js
index a4696280b2..7ec45184f5 100644
--- a/packages/babel-plugin/src/utils/index.js
+++ b/packages/babel-plugin/src/utils/index.js
@@ -1,4 +1,3 @@
-// @flow
export { getLabelFromPath } from './label'
export { getSourceMap } from './source-maps'
export { getTargetClassName } from './get-target-class-name'
diff --git a/packages/babel-plugin/src/utils/label.js b/packages/babel-plugin/src/utils/label.js
index f20ace5a2d..5d4d1f7120 100644
--- a/packages/babel-plugin/src/utils/label.js
+++ b/packages/babel-plugin/src/utils/label.js
@@ -1,20 +1,21 @@
-// @flow
import nodePath from 'path'
+/*
type LabelFormatOptions = {
name: string,
path: string
}
+*/
const invalidClassNameCharacters = /[!"#$%&'()*+,./:;<=>?@[\]^`|}~{]/g
-const sanitizeLabelPart = (labelPart: string) =>
+const sanitizeLabelPart = (labelPart /*: string */) =>
labelPart.trim().replace(invalidClassNameCharacters, '-')
function getLabel(
- identifierName?: string,
- labelFormat?: string | (LabelFormatOptions => string),
- filename: string
+ identifierName /* ?: string */,
+ labelFormat /* ?: string | (LabelFormatOptions => string) */,
+ filename /*: string */
) {
if (!identifierName) return null
@@ -45,7 +46,7 @@ function getLabel(
.replace(/\[dirname\]/gi, sanitizeLabelPart(localDirname))
}
-export function getLabelFromPath(path: *, state: *, t: *) {
+export function getLabelFromPath(path, state, t) {
return getLabel(
getIdentifierName(path, t),
state.opts.labelFormat,
@@ -72,7 +73,6 @@ const getObjPropertyLikeName = (path, t) => {
}
function getDeclaratorName(path, t) {
- // $FlowFixMe
const parent = path.findParent(
p =>
p.isVariableDeclarator() ||
@@ -154,14 +154,13 @@ function getDeclaratorName(path, t) {
return variableDeclarator.node.id.name
}
-function getIdentifierName(path: *, t: *) {
+function getIdentifierName(path, t) {
let objPropertyLikeName = getObjPropertyLikeName(path.parentPath, t)
if (objPropertyLikeName) {
return objPropertyLikeName
}
- // $FlowFixMe
let classOrClassPropertyParent = path.findParent(
p => t.isClassProperty(p) || t.isClass(p)
)
diff --git a/packages/babel-plugin/src/utils/minify.js b/packages/babel-plugin/src/utils/minify.js
index 14281a98ed..7d5c18e79d 100644
--- a/packages/babel-plugin/src/utils/minify.js
+++ b/packages/babel-plugin/src/utils/minify.js
@@ -1,4 +1,3 @@
-// @flow
import { compile } from 'stylis'
const haveSameLocation = (element1, element2) => {
@@ -59,18 +58,17 @@ var stringifyTree = elements => {
.join('')
}
-const interleave = (strings: Array<*>, interpolations: Array<*>) =>
+const interleave = (strings /*: Array<*> */, interpolations /*: Array<*> */) =>
interpolations.reduce(
(array, interp, i) => array.concat([interp], strings[i + 1]),
[strings[0]]
)
-function getDynamicMatches(str: string) {
+function getDynamicMatches(str /*: string */) {
const re = /xxx(\d+):xxx/gm
let match
const matches = []
while ((match = re.exec(str)) !== null) {
- // so that flow doesn't complain
if (match !== null) {
matches.push({
value: match[0],
@@ -84,9 +82,9 @@ function getDynamicMatches(str: string) {
}
function replacePlaceholdersWithExpressions(
- str: string,
- expressions: Array<*>,
- t: *
+ str /*: string */,
+ expressions /*: Array<*> */,
+ t
) {
const matches = getDynamicMatches(str)
if (matches.length === 0) {
@@ -116,15 +114,17 @@ function replacePlaceholdersWithExpressions(
})
return interleave(strings, finalExpressions).filter(
- (node: { value: string }) => {
+ (node /*: { value: string } */) => {
return node.value !== ''
}
)
}
-function createRawStringFromTemplateLiteral(quasi: {
+function createRawStringFromTemplateLiteral(
+ quasi /*: {
quasis: Array<{ value: { cooked: string } }>
-}) {
+} */
+) {
let strs = quasi.quasis.map(x => x.value.cooked)
const src = strs
@@ -140,7 +140,7 @@ function createRawStringFromTemplateLiteral(quasi: {
return src
}
-export default function minify(path: *, t: *): void {
+export default function minify(path, t) {
const quasi = path.node.quasi
const raw = createRawStringFromTemplateLiteral(quasi)
const minified = stringifyTree(toInputTree(compile(raw), []))
diff --git a/packages/babel-plugin/src/utils/object-to-string.js b/packages/babel-plugin/src/utils/object-to-string.js
index a3bfa56460..f275c5b07d 100644
--- a/packages/babel-plugin/src/utils/object-to-string.js
+++ b/packages/babel-plugin/src/utils/object-to-string.js
@@ -1,10 +1,9 @@
-// @flow
import { serializeStyles } from '@emotion/serialize'
// to anyone looking at this, this isn't intended to simplify every single case
// it's meant to simplify the most common cases so i don't want to make it especially complex
// also, this will be unnecessary when prepack is ready
-export function simplifyObject(node: *, t: Object) {
+export function simplifyObject(node, t /*: Object */) {
let finalString = ''
for (let i = 0; i < node.properties.length; i++) {
let property = node.properties[i]
diff --git a/packages/babel-plugin/src/utils/source-maps.js b/packages/babel-plugin/src/utils/source-maps.js
index b499f33cca..e4926711b3 100644
--- a/packages/babel-plugin/src/utils/source-maps.js
+++ b/packages/babel-plugin/src/utils/source-maps.js
@@ -1,4 +1,3 @@
-// @flow
import { SourceMapGenerator } from 'source-map'
import convert from 'convert-source-map'
@@ -6,7 +5,7 @@ function getGeneratorOpts(file) {
return file.opts.generatorOpts ? file.opts.generatorOpts : file.opts
}
-export function makeSourceMapGenerator(file: *) {
+export function makeSourceMapGenerator(file) {
const generatorOpts = getGeneratorOpts(file)
const filename = generatorOpts.sourceFileName
const generator = new SourceMapGenerator({
@@ -19,12 +18,12 @@ export function makeSourceMapGenerator(file: *) {
}
export function getSourceMap(
- offset: {
+ offset /*: {
line: number,
column: number
- },
- state: *
-): string {
+ } */,
+ state
+) /*: string */ {
const generator = makeSourceMapGenerator(state.file)
const generatorOpts = getGeneratorOpts(state.file)
if (
diff --git a/packages/babel-plugin/src/utils/strings.js b/packages/babel-plugin/src/utils/strings.js
index 6c91c62161..5e85223e92 100644
--- a/packages/babel-plugin/src/utils/strings.js
+++ b/packages/babel-plugin/src/utils/strings.js
@@ -1,13 +1,12 @@
-// @flow
import {
getTypeScriptMakeTemplateObjectPath,
isTaggedTemplateTranspiledByBabel
} from './transpiled-output-utils'
export const appendStringReturningExpressionToArguments = (
- t: *,
- path: *,
- expression: *
+ t,
+ path,
+ expression
) => {
let lastIndex = path.node.arguments.length - 1
let last = path.node.arguments[lastIndex]
@@ -44,7 +43,7 @@ export const appendStringReturningExpressionToArguments = (
}
}
-export const joinStringLiterals = (expressions: Array<*>, t: *) => {
+export const joinStringLiterals = (expressions /*: Array<*> */, t) => {
return expressions.reduce((finalExpressions, currentExpression, i) => {
if (!t.isStringLiteral(currentExpression)) {
finalExpressions.push(currentExpression)
diff --git a/packages/babel-plugin/src/utils/transform-expression-with-styles.js b/packages/babel-plugin/src/utils/transform-expression-with-styles.js
index c47e7366e4..0e61f74730 100644
--- a/packages/babel-plugin/src/utils/transform-expression-with-styles.js
+++ b/packages/babel-plugin/src/utils/transform-expression-with-styles.js
@@ -1,5 +1,3 @@
-// @flow
-
import { serializeStyles } from '@emotion/serialize'
import minify from './minify'
import { getLabelFromPath } from './label'
@@ -14,19 +12,15 @@ import createNodeEnvConditional from './create-node-env-conditional'
const CSS_OBJECT_STRINGIFIED_ERROR =
"You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."
-export let transformExpressionWithStyles = ({
+export let transformExpressionWithStyles = (
+ { babel, state, path, shouldLabel, sourceMap = '' } /*: {
babel,
state,
path,
- shouldLabel,
- sourceMap = ''
-}: {
- babel: *,
- state: *,
- path: *,
shouldLabel: boolean,
sourceMap?: string
-}): * => {
+} */
+) => {
const autoLabel = state.opts.autoLabel || 'dev-only'
let t = babel.types
if (t.isTaggedTemplateExpression(path)) {
diff --git a/packages/babel-plugin/src/utils/transformer-macro.js b/packages/babel-plugin/src/utils/transformer-macro.js
index ea10489699..679ad1af38 100644
--- a/packages/babel-plugin/src/utils/transformer-macro.js
+++ b/packages/babel-plugin/src/utils/transformer-macro.js
@@ -1,11 +1,12 @@
-// @flow
import { createMacro } from 'babel-plugin-macros'
+/*
type Transformer = Function
+*/
export function createTransformerMacro(
- transformers: { [key: string]: Transformer | [Transformer, Object] },
- { importSource }: { importSource: string }
+ transformers /*: { [key: string]: Transformer | [Transformer, Object] } */,
+ { importSource } /*: { importSource: string } */
) {
let macro = createMacro(
({ path, source, references, state, babel, isEmotionCall }) => {
diff --git a/packages/babel-plugin/src/utils/transpiled-output-utils.js b/packages/babel-plugin/src/utils/transpiled-output-utils.js
index e6943e3b64..74187e413f 100644
--- a/packages/babel-plugin/src/utils/transpiled-output-utils.js
+++ b/packages/babel-plugin/src/utils/transpiled-output-utils.js
@@ -1,8 +1,6 @@
-// @flow
-
// this only works correctly in modules, but we don't run on scripts anyway, so it's fine
// the difference is that in modules template objects are being cached per call site
-export function getTypeScriptMakeTemplateObjectPath(path: *) {
+export function getTypeScriptMakeTemplateObjectPath(path) {
if (path.node.arguments.length === 0) {
return null
}
@@ -28,7 +26,7 @@ export function getTypeScriptMakeTemplateObjectPath(path: *) {
// we could push them to found array expressions, as we do it for TS-transpile output ¯\_(ツ)_/¯
// it seems overly complicated though - mainly because we'd also have to check against existing stuff of a particular type (source maps & labels)
// considering Babel double-transpilation as a valid use case seems rather far-fetched
-export function isTaggedTemplateTranspiledByBabel(path: *) {
+export function isTaggedTemplateTranspiledByBabel(path) {
if (path.node.arguments.length === 0) {
return false
}
diff --git a/packages/cache/__tests__/hydration.js b/packages/cache/__tests__/hydration.js
index 132f26237b..851e3ffb94 100644
--- a/packages/cache/__tests__/hydration.js
+++ b/packages/cache/__tests__/hydration.js
@@ -1,4 +1,3 @@
-// @flow
import { safeQuerySelector } from 'test-utils'
import hashString from '@emotion/hash'
import createCache from '@emotion/cache'
diff --git a/packages/cache/__tests__/index.js b/packages/cache/__tests__/index.js
index 15751f2166..d89af730b9 100644
--- a/packages/cache/__tests__/index.js
+++ b/packages/cache/__tests__/index.js
@@ -1,4 +1,3 @@
-// @flow
/** @jsx jsx */
import 'test-utils/next-env'
import { safeQuerySelector } from 'test-utils'
diff --git a/packages/cache/src/index.js b/packages/cache/src/index.js
index 39d66bf915..82378f02b0 100644
--- a/packages/cache/src/index.js
+++ b/packages/cache/src/index.js
@@ -1,6 +1,5 @@
-// @flow
import { StyleSheet } from '@emotion/sheet'
-import { type EmotionCache, type SerializedStyles } from '@emotion/utils'
+/* import { type EmotionCache, type SerializedStyles } from '@emotion/utils' */
import {
serialize,
compile,
@@ -18,10 +17,11 @@ import {
incorrectImportAlarm
} from './stylis-plugins'
import { prefixer } from './prefixer'
-import type { StylisPlugin } from './types'
+/* import type { StylisPlugin } from './types' */
let isBrowser = typeof document !== 'undefined'
+/*
export type Options = {
nonce?: string,
stylisPlugins?: StylisPlugin[],
@@ -31,6 +31,7 @@ export type Options = {
prepend?: boolean,
insertionPoint?: HTMLElement
}
+*/
let getServerStylisCache = isBrowser
? undefined
@@ -43,7 +44,7 @@ let getServerStylisCache = isBrowser
const defaultStylisPlugins = [prefixer]
-let createCache = (options: Options): EmotionCache => {
+let createCache = (options /*: Options */) /*: EmotionCache */ => {
let key = options.key
if (process.env.NODE_ENV !== 'production' && !key) {
@@ -62,21 +63,19 @@ let createCache = (options: Options): EmotionCache => {
// document.head is a safe place to move them to(though note document.head is not necessarily the last place they will be)
// note this very very intentionally targets all style elements regardless of the key to ensure
// that creating a cache works inside of render of a React component
- Array.prototype.forEach.call(ssrStyles, (node: HTMLStyleElement) => {
+ Array.prototype.forEach.call(ssrStyles, (node /*: HTMLStyleElement */) => {
// we want to only move elements which have a space in the data-emotion attribute value
// because that indicates that it is an Emotion 11 server-side rendered style elements
// while we will already ignore Emotion 11 client-side inserted styles because of the :not([data-s]) part in the selector
// Emotion 10 client-side inserted styles did not have data-s (but importantly did not have a space in their data-emotion attributes)
// so checking for the space ensures that loading Emotion 11 after Emotion 10 has inserted some styles
// will not result in the Emotion 10 styles being destroyed
- const dataEmotionAttribute = ((node.getAttribute(
- 'data-emotion'
- ): any): string)
+ const dataEmotionAttribute = node.getAttribute('data-emotion')
if (dataEmotionAttribute.indexOf(' ') === -1) {
return
}
- ;((document.head: any): HTMLHeadElement).appendChild(node)
+ document.head.appendChild(node)
node.setAttribute('data-s', '')
})
}
@@ -84,7 +83,6 @@ let createCache = (options: Options): EmotionCache => {
const stylisPlugins = options.stylisPlugins || defaultStylisPlugins
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`
@@ -92,20 +90,17 @@ let createCache = (options: Options): EmotionCache => {
}
}
let inserted = {}
- let container: Node
+ let container /* : Node */
const nodesToHydrate = []
if (isBrowser) {
- container = options.container || ((document.head: any): HTMLHeadElement)
+ container = options.container || document.head
Array.prototype.forEach.call(
// this means we will ignore elements which don't have a space in them which
// means that the style elements we're looking at are only Emotion 11 server-rendered style elements
document.querySelectorAll(`style[data-emotion^="${key} "]`),
- (node: HTMLStyleElement) => {
- const attrib = ((node.getAttribute(`data-emotion`): any): string).split(
- ' '
- )
- // $FlowFixMe
+ (node /*: HTMLStyleElement */) => {
+ const attrib = node.getAttribute(`data-emotion`).split(' ')
for (let i = 1; i < attrib.length; i++) {
inserted[attrib[i]] = true
}
@@ -114,13 +109,12 @@ let createCache = (options: Options): EmotionCache => {
)
}
- let insert: (
+ let insert /*: (
selector: string,
serialized: SerializedStyles,
sheet: StyleSheet,
shouldCache: boolean
- ) => string | void
-
+ ) => string | void */
const omnipresentPlugins = [compat, removeLabel]
if (process.env.NODE_ENV !== 'production') {
@@ -162,19 +156,19 @@ let createCache = (options: Options): EmotionCache => {
const stylis = styles => serialize(compile(styles), serializer)
insert = (
- selector: string,
- serialized: SerializedStyles,
- sheet: StyleSheet,
- shouldCache: boolean
- ): void => {
+ selector /*: string */,
+ serialized /*: SerializedStyles */,
+ sheet /*: StyleSheet */,
+ shouldCache /*: boolean */
+ ) /*: void */ => {
currentSheet = sheet
if (
process.env.NODE_ENV !== 'production' &&
serialized.map !== undefined
) {
currentSheet = {
- insert: (rule: string) => {
- sheet.insert(rule + ((serialized.map: any): string))
+ insert: (rule /*: string */) => {
+ sheet.insert(rule + serialized.map)
}
}
}
@@ -192,9 +186,11 @@ let createCache = (options: Options): EmotionCache => {
)
const stylis = styles => serialize(compile(styles), serializer)
- // $FlowFixMe
let serverStylisCache = getServerStylisCache(stylisPlugins)(key)
- let getRules = (selector: string, serialized: SerializedStyles): string => {
+ let getRules = (
+ selector /*: string */,
+ serialized /*: SerializedStyles */
+ ) /*: string */ => {
let name = serialized.name
if (serverStylisCache[name] === undefined) {
serverStylisCache[name] = stylis(
@@ -204,11 +200,11 @@ let createCache = (options: Options): EmotionCache => {
return serverStylisCache[name]
}
insert = (
- selector: string,
- serialized: SerializedStyles,
- sheet: StyleSheet,
- shouldCache: boolean
- ): string | void => {
+ selector /*: string */,
+ serialized /*: SerializedStyles */,
+ sheet /*: StyleSheet */,
+ shouldCache /*: boolean */
+ ) /*: string | void */ => {
let name = serialized.name
let rules = getRules(selector, serialized)
if (cache.compat === undefined) {
@@ -245,11 +241,11 @@ let createCache = (options: Options): EmotionCache => {
}
}
- const cache: EmotionCache = {
+ const cache /*: EmotionCache */ = {
key,
sheet: new StyleSheet({
key,
- container: ((container: any): Node),
+ container,
nonce: options.nonce,
speedy: options.speedy,
prepend: options.prepend,
diff --git a/packages/cache/src/types.js b/packages/cache/src/types.js
index 92312fb30c..f02fb33414 100644
--- a/packages/cache/src/types.js
+++ b/packages/cache/src/types.js
@@ -1,14 +1,13 @@
-// @flow
-
+/*
export type StylisElement = {
- type: string,
- value: string,
- props: Array,
- root: StylisElement | null,
- children: Array,
- line: number,
- column: number,
- length: number,
+ type: string
+ value: string
+ props: Array
+ root: StylisElement | null
+ children: Array
+ line: number
+ column: number
+ length: number
return: string
}
export type StylisPluginCallback = (
@@ -24,3 +23,4 @@ export type StylisPlugin = (
children: Array,
callback: StylisPluginCallback
) => string | void
+*/
diff --git a/packages/cache/types/index.d.ts b/packages/cache/types/index.d.ts
index 7822587db8..3bba3ded23 100644
--- a/packages/cache/types/index.d.ts
+++ b/packages/cache/types/index.d.ts
@@ -1,5 +1,8 @@
// Definitions by: Junyoung Clare Jang
// TypeScript Version: 2.2
+
+///
+
import { EmotionCache } from '@emotion/utils'
export { EmotionCache }
diff --git a/packages/css/create-instance/package.json b/packages/css/create-instance/package.json
index 203a18da18..bd294c0d39 100644
--- a/packages/css/create-instance/package.json
+++ b/packages/css/create-instance/package.json
@@ -2,7 +2,7 @@
"main": "dist/emotion-css-create-instance.cjs.js",
"module": "dist/emotion-css-create-instance.esm.js",
"umd:main": "dist/emotion-css-create-instance.umd.min.js",
- "types": "../types/create-instance",
+ "types": "dist/emotion-css-create-instance.cjs.d.ts",
"preconstruct": {
"umdName": "createEmotion"
}
diff --git a/packages/css/macro.js.flow b/packages/css/macro.js.flow
deleted file mode 100644
index 63ae97e66d..0000000000
--- a/packages/css/macro.js.flow
+++ /dev/null
@@ -1,2 +0,0 @@
-// @flow
-export * from './src/index.js'
diff --git a/packages/css/package.json b/packages/css/package.json
index caed679ae1..c119f34f87 100644
--- a/packages/css/package.json
+++ b/packages/css/package.json
@@ -4,7 +4,7 @@
"description": "The Next Generation of CSS-in-JS.",
"main": "dist/emotion-css.cjs.js",
"module": "dist/emotion-css.esm.js",
- "types": "types/index.d.ts",
+ "types": "dist/emotion-css.cjs.d.ts",
"files": [
"src",
"dist",
@@ -64,8 +64,8 @@
"preconstruct": {
"umdName": "emotion",
"entrypoints": [
- "./index.js",
- "./create-instance.js"
+ "./index.ts",
+ "./create-instance.ts"
],
"exports": {
"extra": {
diff --git a/packages/css/src/create-instance.d.ts b/packages/css/src/create-instance.d.ts
deleted file mode 100644
index 5329dce3b6..0000000000
--- a/packages/css/src/create-instance.d.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from '../types/create-instance'
-export { default } from '../types/create-instance'
diff --git a/packages/css/src/create-instance.js b/packages/css/src/create-instance.ts
similarity index 52%
rename from packages/css/src/create-instance.js
rename to packages/css/src/create-instance.ts
index 3b18761368..2bf7cc2813 100644
--- a/packages/css/src/create-instance.js
+++ b/packages/css/src/create-instance.ts
@@ -1,21 +1,80 @@
-// @flow
import createCache from '@emotion/cache'
-import { serializeStyles } from '@emotion/serialize'
+import {
+ serializeStyles,
+ CSSInterpolation,
+ Interpolation
+} from '@emotion/serialize'
import {
insertStyles,
getRegisteredStyles,
- type EmotionCache,
- type SerializedStyles
+ SerializedStyles,
+ RegisteredCache
} from '@emotion/utils'
+import { EmotionCache, Options } from '@emotion/cache'
+import { StyleSheet } from '@emotion/sheet'
+
+export type {
+ CSSInterpolation,
+ ArrayCSSInterpolation,
+ ComponentSelector,
+ CSSObject
+} from '@emotion/serialize'
-function insertWithoutScoping(cache, serialized: SerializedStyles) {
+function insertWithoutScoping(
+ cache: EmotionCache,
+ serialized: SerializedStyles
+) {
if (cache.inserted[serialized.name] === undefined) {
return cache.insert('', serialized, cache.sheet, true)
}
}
-function merge(registered: Object, css: (*) => string, className: string) {
- const registeredStyles = []
+export type { EmotionCache, Options }
+
+export interface ArrayClassNamesArg extends Array {}
+export type ClassNamesArg =
+ | undefined
+ | null
+ | string
+ | boolean
+ | { [className: string]: boolean | null | undefined }
+ | ArrayClassNamesArg
+
+export interface CSSStyleSheet extends StyleSheet {
+ speedy(value: boolean): void
+}
+
+export interface Emotion {
+ css(template: TemplateStringsArray, ...args: Array): string
+ css(...args: Array): string
+ cx(...classNames: Array): string
+ flush(): void
+ hydrate(ids: Array): void
+ injectGlobal(
+ template: TemplateStringsArray,
+ ...args: Array
+ ): void
+ injectGlobal(...args: Array): void
+ keyframes(
+ template: TemplateStringsArray,
+ ...args: Array
+ ): string
+ keyframes(...args: Array): string
+ sheet: CSSStyleSheet
+ cache: EmotionCache
+ merge(className: string): string
+ getRegisteredStyles(
+ registeredStyles: Array,
+ className: string
+ ): string
+}
+
+function merge(
+ registered: RegisteredCache,
+ css: Emotion['css'],
+ className: string
+) {
+ const registeredStyles: string[] = []
const rawClassName = getRegisteredStyles(
registered,
registeredStyles,
@@ -28,60 +87,29 @@ function merge(registered: Object, css: (*) => string, className: string) {
return rawClassName + css(registeredStyles)
}
-export type Interpolation = any
-export type Interpolations = Array
-
-type CreateStyles = (...args: Interpolations) => ReturnValue
-
-type ClassNameArg =
- | string
- | boolean
- | { [key: string]: boolean | void | null }
- | Array
- | void
- | null
-
-declare class StyleSheet {
- insert(rule: string): void;
- flush(): void;
- speedy(newVal: boolean): void;
- tags: Array;
- isSpeedy: number;
- ctr: number;
-}
-
-export type Emotion = {
- css: CreateStyles,
- cx: (...classNames: Array) => string,
- flush: () => void,
- hydrate: (ids: Array) => void,
- injectGlobal: CreateStyles,
- keyframes: CreateStyles,
- sheet: StyleSheet,
- cache: EmotionCache,
- merge: *,
- getRegisteredStyles: *
-}
-
-let createEmotion = (options: *): Emotion => {
+let createEmotion = (options: Options): Emotion => {
let cache = createCache(options)
- // $FlowFixMe
- cache.sheet.speedy = function (value: boolean) {
+ ;(cache.sheet as CSSStyleSheet).speedy = function (value: boolean) {
if (process.env.NODE_ENV !== 'production' && this.ctr !== 0) {
throw new Error('speedy must be changed before any rules are inserted')
}
this.isSpeedy = value
}
+
cache.compat = true
- let css = (...args) => {
+ let css: Emotion['css'] = (
+ ...args: (TemplateStringsArray | Interpolation)[]
+ ) => {
let serialized = serializeStyles(args, cache.registered, undefined)
insertStyles(cache, serialized, false)
return `${cache.key}-${serialized.name}`
}
- let keyframes = (...args) => {
+ let keyframes: Emotion['keyframes'] = (
+ ...args: (TemplateStringsArray | Interpolation)[]
+ ) => {
let serialized = serializeStyles(args, cache.registered)
let animation = `animation-${serialized.name}`
insertWithoutScoping(cache, {
@@ -91,12 +119,14 @@ let createEmotion = (options: *): Emotion => {
return animation
}
- let injectGlobal = (...args) => {
+ let injectGlobal: Emotion['injectGlobal'] = (
+ ...args: (TemplateStringsArray | Interpolation)[]
+ ) => {
let serialized = serializeStyles(args, cache.registered)
insertWithoutScoping(cache, serialized)
}
- let cx = (...args) => {
+ let cx: Emotion['cx'] = (...args) => {
return merge(cache.registered, css, classnames(args))
}
return {
@@ -104,7 +134,7 @@ let createEmotion = (options: *): Emotion => {
cx,
injectGlobal,
keyframes,
- hydrate(ids: Array) {
+ hydrate(ids) {
ids.forEach(key => {
cache.inserted[key] = true
})
@@ -114,15 +144,14 @@ let createEmotion = (options: *): Emotion => {
cache.inserted = {}
cache.sheet.flush()
},
- // $FlowFixMe
- sheet: cache.sheet,
+ sheet: cache.sheet as CSSStyleSheet,
cache,
getRegisteredStyles: getRegisteredStyles.bind(null, cache.registered),
merge: merge.bind(null, cache.registered, css)
}
}
-let classnames = args => {
+let classnames = (args: ClassNamesArg[]) => {
let cls = ''
for (let i = 0; i < args.length; i++) {
let arg = args[i]
diff --git a/packages/css/src/index.d.ts b/packages/css/src/index.d.ts
deleted file mode 100644
index 51a3b4100a..0000000000
--- a/packages/css/src/index.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from '../types'
diff --git a/packages/css/src/index.js b/packages/css/src/index.ts
similarity index 95%
rename from packages/css/src/index.js
rename to packages/css/src/index.ts
index 523fed93ef..9e4000e3d8 100644
--- a/packages/css/src/index.js
+++ b/packages/css/src/index.ts
@@ -1,4 +1,3 @@
-// @flow
import createEmotion from './create-instance'
export const {
diff --git a/packages/css/test/css.test.js b/packages/css/test/css.test.js
index b32630a6d1..7b44dab7a8 100644
--- a/packages/css/test/css.test.js
+++ b/packages/css/test/css.test.js
@@ -1,4 +1,3 @@
-// @flow
import 'test-utils/legacy-env'
import React from 'react'
import renderer from 'react-test-renderer'
diff --git a/packages/css/test/cx.test.js b/packages/css/test/cx.test.js
index fc074cbbaf..30370209ed 100644
--- a/packages/css/test/cx.test.js
+++ b/packages/css/test/cx.test.js
@@ -1,4 +1,3 @@
-// @flow
import 'test-utils/legacy-env'
import React from 'react'
import renderer from 'react-test-renderer'
diff --git a/packages/css/test/inject-global.test.js b/packages/css/test/inject-global.test.js
index 44e9d0d66e..44050042ee 100644
--- a/packages/css/test/inject-global.test.js
+++ b/packages/css/test/inject-global.test.js
@@ -1,4 +1,3 @@
-// @flow
import 'test-utils/legacy-env'
import { injectGlobal, sheet, flush, css } from '@emotion/css'
diff --git a/packages/css/test/instance/css.test.js b/packages/css/test/instance/css.test.js
index 73685174d9..67a2a02ea4 100644
--- a/packages/css/test/instance/css.test.js
+++ b/packages/css/test/instance/css.test.js
@@ -1,4 +1,3 @@
-// @flow
import 'test-utils/next-env'
import React from 'react'
import renderer from 'react-test-renderer'
diff --git a/packages/css/test/instance/emotion-instance.js b/packages/css/test/instance/emotion-instance.js
index 943d712879..59a4d1f8b6 100644
--- a/packages/css/test/instance/emotion-instance.js
+++ b/packages/css/test/instance/emotion-instance.js
@@ -1,4 +1,3 @@
-// @flow
import createEmotion from '@emotion/css/create-instance'
import createEmotionServer from '@emotion/server/create-instance'
@@ -12,7 +11,6 @@ export let container
if (typeof document !== 'undefined') {
container = document.createElement('div')
- // $FlowFixMe
document.head.appendChild(container)
}
diff --git a/packages/css/test/instance/instance.test.js b/packages/css/test/instance/instance.test.js
index af9f5e668d..b3ee02629b 100644
--- a/packages/css/test/instance/instance.test.js
+++ b/packages/css/test/instance/instance.test.js
@@ -1,4 +1,3 @@
-// @flow
import createEmotion from '@emotion/css/create-instance'
import { container, css, sheet } from './emotion-instance'
diff --git a/packages/css/test/keyframes.test.js b/packages/css/test/keyframes.test.js
index fc2a5b0626..961568ca82 100644
--- a/packages/css/test/keyframes.test.js
+++ b/packages/css/test/keyframes.test.js
@@ -1,4 +1,3 @@
-// @flow
import 'test-utils/legacy-env'
import React from 'react'
import renderer from 'react-test-renderer'
diff --git a/packages/css/test/no-babel/index.test.js b/packages/css/test/no-babel/index.test.js
index 527671accf..2b0daf8e72 100644
--- a/packages/css/test/no-babel/index.test.js
+++ b/packages/css/test/no-babel/index.test.js
@@ -1,4 +1,3 @@
-// @flow
import 'test-utils/legacy-env'
import React from 'react'
import renderer from 'react-test-renderer'
@@ -228,7 +227,7 @@ describe('css', () => {
expect(tree).toMatchSnapshot()
})
test('name with class component', () => {
- class SomeComponent extends React.Component<{ className: string }> {
+ class SomeComponent extends React.Component /* <{ className: string }> */ {
render() {
return
}
diff --git a/packages/css/test/no-babel/warnings.test.js b/packages/css/test/no-babel/warnings.test.js
index 3e1e74430a..67cbc5e9ee 100644
--- a/packages/css/test/no-babel/warnings.test.js
+++ b/packages/css/test/no-babel/warnings.test.js
@@ -1,8 +1,6 @@
-// @flow
import 'test-utils/legacy-env'
import { css } from '@emotion/css'
-// $FlowFixMe
console.error = jest.fn()
afterEach(() => {
@@ -16,7 +14,7 @@ it('warns about illegal escape sequences inside first quasi of template literal'
}
`
- expect((console.error: any).mock.calls[0]).toMatchInlineSnapshot(`
+ expect(console.error.mock.calls[0]).toMatchInlineSnapshot(`
[
"You have illegal escape sequence in your template literal, most likely inside content's property value.
Because you write your CSS inside a JavaScript string you actually have to do double escaping, so for example "content: '\\00d7';" should become "content: '\\\\00d7';".
@@ -36,7 +34,7 @@ it('warns about illegal escape sequences inside non-first quasi of template lite
}
`
- expect((console.error: any).mock.calls[0]).toMatchInlineSnapshot(`
+ expect(console.error.mock.calls[0]).toMatchInlineSnapshot(`
[
"You have illegal escape sequence in your template literal, most likely inside content's property value.
Because you write your CSS inside a JavaScript string you actually have to do double escaping, so for example "content: '\\00d7';" should become "content: '\\\\00d7';".
diff --git a/packages/css/test/selectivity.test.js b/packages/css/test/selectivity.test.js
index dd66dc32b0..c6782b88d2 100644
--- a/packages/css/test/selectivity.test.js
+++ b/packages/css/test/selectivity.test.js
@@ -1,4 +1,3 @@
-// @flow
import 'test-utils/legacy-env'
import { css, sheet, flush } from '@emotion/css'
diff --git a/packages/css/test/sheet.dom.test.js b/packages/css/test/sheet.dom.test.js
index d482d84c02..90833e56e1 100644
--- a/packages/css/test/sheet.dom.test.js
+++ b/packages/css/test/sheet.dom.test.js
@@ -1,4 +1,3 @@
-// @flow
import { sheet } from '@emotion/css'
const consoleError = console.error
diff --git a/packages/css/test/warnings.test.js b/packages/css/test/warnings.test.js
index 61c4235214..0996161b15 100644
--- a/packages/css/test/warnings.test.js
+++ b/packages/css/test/warnings.test.js
@@ -1,11 +1,9 @@
-// @flow
import 'test-utils/legacy-env'
import { css } from '@emotion/css'
import createCss from '@emotion/css/create-instance'
import * as React from 'react'
import renderer from 'react-test-renderer'
-// $FlowFixMe
console.error = jest.fn()
const validValues = [
@@ -67,7 +65,7 @@ it('does warn when @import rule is being inserted after order-insensitive rules'
injectGlobal`.thing {display:flex;}`
injectGlobal`@import 'custom.css';`
- expect((console.error: any).mock.calls).toMatchInlineSnapshot(`
+ expect(console.error.mock.calls).toMatchInlineSnapshot(`
[
[
"You're attempting to insert the following rule:
diff --git a/packages/css/types/create-instance.d.ts b/packages/css/types/create-instance.d.ts
index 9e560390f1..e505b19935 100644
--- a/packages/css/types/create-instance.d.ts
+++ b/packages/css/types/create-instance.d.ts
@@ -1,55 +1,4 @@
// Definitions by: Junyoung Clare Jang
// TypeScript Version: 2.8
-
-import { EmotionCache, Options } from '@emotion/cache'
-import { CSSInterpolation } from '@emotion/serialize'
-import { StyleSheet } from '@emotion/sheet'
-
-export {
- CSSInterpolation,
- ArrayCSSInterpolation,
- ComponentSelector,
- CSSObject
-} from '@emotion/serialize'
-
-export { EmotionCache, Options }
-
-export interface ArrayClassNamesArg extends Array {}
-export type ClassNamesArg =
- | undefined
- | null
- | string
- | boolean
- | { [className: string]: boolean | null | undefined }
- | ArrayClassNamesArg
-
-export interface CSSStyleSheet extends StyleSheet {
- speedy(value: boolean): void
-}
-
-export interface Emotion {
- css(template: TemplateStringsArray, ...args: Array): string
- css(...args: Array): string
- cx(...classNames: Array): string
- flush(): void
- hydrate(ids: Array): void
- injectGlobal(
- template: TemplateStringsArray,
- ...args: Array
- ): void
- injectGlobal(...args: Array): void
- keyframes(
- template: TemplateStringsArray,
- ...args: Array
- ): string
- keyframes(...args: Array): string
- sheet: CSSStyleSheet
- cache: EmotionCache
- merge(className: string): string
- getRegisteredStyles(
- registeredStyles: Array,
- className: string
- ): string
-}
-
-export default function createEmotion(options?: Options): Emotion
+export * from '../create-instance'
+export { default } from '../create-instance'
diff --git a/packages/css/types/index.d.ts b/packages/css/types/index.d.ts
index 7efec6edee..23f9a3c26e 100644
--- a/packages/css/types/index.d.ts
+++ b/packages/css/types/index.d.ts
@@ -1,26 +1,3 @@
-// Definitions by: Junyoung Clare Jang
-// TypeScript Version: 2.8
+///
-import { Emotion } from './create-instance'
-
-export {
- ArrayClassNamesArg,
- ArrayCSSInterpolation,
- ClassNamesArg,
- ComponentSelector,
- EmotionCache,
- CSSInterpolation,
- CSSObject,
- CSSStyleSheet
-} from './create-instance'
-
-export const flush: Emotion['flush']
-export const hydrate: Emotion['hydrate']
-export const cx: Emotion['cx']
-export const merge: Emotion['merge']
-export const getRegisteredStyles: Emotion['getRegisteredStyles']
-export const css: Emotion['css']
-export const injectGlobal: Emotion['injectGlobal']
-export const keyframes: Emotion['keyframes']
-export const sheet: Emotion['sheet']
-export const cache: Emotion['cache']
+export * from '..'
diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json
index 996c688f92..9db1a82c36 100644
--- a/packages/eslint-plugin/package.json
+++ b/packages/eslint-plugin/package.json
@@ -27,7 +27,12 @@
"peerDependencies": {
"eslint": "6 || 7 || 8"
},
+ "dependencies": {
+ "@typescript-eslint/utils": "^5.25.0"
+ },
"devDependencies": {
- "eslint": "^7.10.0"
+ "@types/eslint": "^7.0.0",
+ "eslint": "^7.10.0",
+ "resolve-from": "^5.0.0"
}
}
diff --git a/packages/eslint-plugin/src/index.js b/packages/eslint-plugin/src/index.ts
similarity index 94%
rename from packages/eslint-plugin/src/index.js
rename to packages/eslint-plugin/src/index.ts
index e626a190cb..3c27f57e22 100644
--- a/packages/eslint-plugin/src/index.js
+++ b/packages/eslint-plugin/src/index.ts
@@ -1,5 +1,3 @@
-// @flow
-
import importFromEmotion from './rules/import-from-emotion'
import noVanilla from './rules/no-vanilla'
import syntaxPreference from './rules/syntax-preference'
@@ -7,7 +5,7 @@ import styledImport from './rules/styled-import'
import jsxImport from './rules/jsx-import'
import pkgRenaming from './rules/pkg-renaming'
-export let rules = {
+export const rules = {
'import-from-emotion': importFromEmotion,
'no-vanilla': noVanilla,
'syntax-preference': syntaxPreference,
diff --git a/packages/eslint-plugin/src/rules/import-from-emotion.js b/packages/eslint-plugin/src/rules/import-from-emotion.js
deleted file mode 100644
index 7889e3ca5b..0000000000
--- a/packages/eslint-plugin/src/rules/import-from-emotion.js
+++ /dev/null
@@ -1,42 +0,0 @@
-export default {
- meta: {
- fixable: 'code'
- },
- create(context) {
- return {
- ImportDeclaration(node) {
- if (
- node.source.value === 'react-emotion' &&
- node.specifiers.some(x => x.type !== 'ImportDefaultSpecifier')
- ) {
- context.report({
- node: node.source,
- message: `emotion's exports should be imported directly from emotion rather than from react-emotion`,
- fix(fixer) {
- if (node.specifiers[0].type === 'ImportNamespaceSpecifier') {
- return
- }
- // default specifiers are always first
- if (node.specifiers[0].type === 'ImportDefaultSpecifier') {
- return fixer.replaceText(
- node,
- `import ${
- node.specifiers[0].local.name
- } from '@emotion/styled';\nimport { ${node.specifiers
- .filter(x => x.type === 'ImportSpecifier')
- .map(x =>
- x.local.name === x.imported.name
- ? x.local.name
- : `${x.imported.name} as ${x.local.name}`
- )
- .join(', ')} } from 'emotion';`
- )
- }
- return fixer.replaceText(node.source, "'emotion'")
- }
- })
- }
- }
- }
- }
-}
diff --git a/packages/eslint-plugin/src/rules/import-from-emotion.ts b/packages/eslint-plugin/src/rules/import-from-emotion.ts
new file mode 100644
index 0000000000..c390ff1d74
--- /dev/null
+++ b/packages/eslint-plugin/src/rules/import-from-emotion.ts
@@ -0,0 +1,69 @@
+import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils'
+import { createRule } from '../utils'
+
+const messages = {
+ incorrectImport: `emotion's exports should be imported directly from emotion rather than from react-emotion`
+}
+
+export default createRule({
+ name: __filename,
+ meta: {
+ docs: {
+ description: 'Ensure styled is imported from @emotion/styled',
+ recommended: false
+ },
+ fixable: 'code',
+ messages,
+ schema: [],
+ type: 'problem'
+ },
+ defaultOptions: [],
+ create(context) {
+ return {
+ ImportDeclaration(node) {
+ if (
+ node.source.value === 'react-emotion' &&
+ node.specifiers.some(
+ x => x.type !== AST_NODE_TYPES.ImportDefaultSpecifier
+ )
+ ) {
+ context.report({
+ node: node.source,
+ messageId: 'incorrectImport',
+ fix(fixer) {
+ if (
+ node.specifiers[0].type ===
+ AST_NODE_TYPES.ImportNamespaceSpecifier
+ ) {
+ return null
+ }
+ // default specifiers are always first
+ if (
+ node.specifiers[0].type ===
+ AST_NODE_TYPES.ImportDefaultSpecifier
+ ) {
+ return fixer.replaceText(
+ node,
+ `import ${
+ node.specifiers[0].local.name
+ } from '@emotion/styled';\nimport { ${node.specifiers
+ .filter(
+ (x): x is TSESTree.ImportSpecifier =>
+ x.type === AST_NODE_TYPES.ImportSpecifier
+ )
+ .map(x =>
+ x.local.name === x.imported.name
+ ? x.local.name
+ : `${x.imported.name} as ${x.local.name}`
+ )
+ .join(', ')} } from 'emotion';`
+ )
+ }
+ return fixer.replaceText(node.source, "'emotion'")
+ }
+ })
+ }
+ }
+ }
+ }
+})
diff --git a/packages/eslint-plugin/src/rules/jsx-import.js b/packages/eslint-plugin/src/rules/jsx-import.ts
similarity index 57%
rename from packages/eslint-plugin/src/rules/jsx-import.js
rename to packages/eslint-plugin/src/rules/jsx-import.ts
index 8b7cab8a65..2ee930f8d2 100644
--- a/packages/eslint-plugin/src/rules/jsx-import.js
+++ b/packages/eslint-plugin/src/rules/jsx-import.ts
@@ -1,3 +1,6 @@
+import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils'
+import { createRule, REPO_URL } from '../utils'
+
const JSX_ANNOTATION_REGEX = /\*?\s*@jsx\s+([^\s]+)/
const JSX_IMPORT_SOURCE_REGEX = /\*?\s*@jsxImportSource\s+([^\s]+)/
@@ -6,9 +9,34 @@ const JSX_IMPORT_SOURCE_REGEX = /\*?\s*@jsxImportSource\s+([^\s]+)/
// to
//
+ import { css }
-export default {
+declare module '@typescript-eslint/utils/dist/ts-eslint/Rule' {
+ export interface SharedConfigurationSettings {
+ react?: { pragma?: string }
+ }
+}
+
+type JSXConfig = {
+ runtime: string
+ importSource?: string
+}
+
+type RuleOptions = [(JSXConfig | string)?]
+
+const messages = {
+ cssProp: `The css prop can only be used if jsxImportSource is set to {{ importSource }}`,
+ cssPropWithPragma: `The css prop can only be used if jsx from @emotion/react is imported and it is set as the jsx pragma`,
+ templateLiterals: `Template literals should be replaced with tagged template literals using \`css\` when using the css prop`
+}
+
+export default createRule({
+ name: __filename,
meta: {
+ docs: {
+ description: 'Ensure jsx from @emotion/react is imported',
+ recommended: false
+ },
fixable: 'code',
+ messages,
schema: {
type: 'array',
items: {
@@ -29,11 +57,14 @@ export default {
},
uniqueItems: true,
minItems: 0
- }
+ },
+ type: 'problem'
},
+ defaultOptions: [],
create(context) {
const jsxRuntimeMode = context.options.find(
- option => option && option.runtime === 'automatic'
+ (option): option is JSXConfig =>
+ typeof option === 'object' && option.runtime === 'automatic'
)
if (jsxRuntimeMode) {
@@ -42,15 +73,14 @@ export default {
if (node.name.name !== 'css') {
return
}
- const importSource =
- (jsxRuntimeMode || {}).importSource || '@emotion/react'
- let jsxImportSourcePragmaNode
+ const importSource = jsxRuntimeMode?.importSource || '@emotion/react'
+ let jsxImportSourcePragmaComment: TSESTree.Comment | null = null
let jsxImportSourceMatch
let validJsxImportSource = false
let sourceCode = context.getSourceCode()
- let pragma = sourceCode.getAllComments().find(node => {
- if (JSX_IMPORT_SOURCE_REGEX.test(node.value)) {
- jsxImportSourcePragmaNode = node
+ let pragma = sourceCode.getAllComments().find(comment => {
+ if (JSX_IMPORT_SOURCE_REGEX.test(comment.value)) {
+ jsxImportSourcePragmaComment = comment
return true
}
})
@@ -65,7 +95,8 @@ export default {
if (!jsxImportSourceMatch) {
context.report({
node,
- message: `The css prop can only be used if jsxImportSource is set to ${importSource}`,
+ messageId: 'cssProp',
+ data: { importSource },
fix(fixer) {
return fixer.insertTextBefore(
sourceCode.ast.body[0],
@@ -73,13 +104,21 @@ export default {
)
}
})
- } else if (!validJsxImportSource && jsxImportSourcePragmaNode) {
+ } else if (!validJsxImportSource && jsxImportSourcePragmaComment) {
context.report({
node,
- message: `The css prop can only be used if jsxImportSource is set to ${importSource}`,
+ messageId: 'cssProp',
+ data: { importSource },
fix(fixer) {
+ /* istanbul ignore if */
+ if (jsxImportSourcePragmaComment === null) {
+ throw new Error(
+ `Unexpected null when attempting to fix ${context.getFilename()} - please file a github issue at ${REPO_URL}`
+ )
+ }
+
return fixer.replaceText(
- jsxImportSourcePragmaNode,
+ jsxImportSourcePragmaComment,
`/** @jsxImportSource ${importSource} */`
)
}
@@ -95,12 +134,12 @@ export default {
return
}
let hasJsxImport = false
- let emotionCoreNode = null
- let local = null
+ let emotionCoreNode = null as TSESTree.ImportDeclaration | null
+ let local: string | null = null
let sourceCode = context.getSourceCode()
sourceCode.ast.body.forEach(x => {
if (
- x.type === 'ImportDeclaration' &&
+ x.type === AST_NODE_TYPES.ImportDeclaration &&
(x.source.value === '@emotion/react' ||
x.source.value === '@emotion/core')
) {
@@ -108,13 +147,15 @@ export default {
if (
x.specifiers.length === 1 &&
- x.specifiers[0].type === 'ImportNamespaceSpecifier'
+ x.specifiers[0].type === AST_NODE_TYPES.ImportNamespaceSpecifier
) {
hasJsxImport = true
local = x.specifiers[0].local.name + '.jsx'
} else {
let jsxSpecifier = x.specifiers.find(
- x => x.type === 'ImportSpecifier' && x.imported.name === 'jsx'
+ x =>
+ x.type === AST_NODE_TYPES.ImportSpecifier &&
+ x.imported.name === 'jsx'
)
if (jsxSpecifier) {
hasJsxImport = true
@@ -138,10 +179,16 @@ export default {
if (!hasJsxImport || !hasSetPragma) {
context.report({
node,
- message:
- 'The css prop can only be used if jsx from @emotion/react is imported and it is set as the jsx pragma',
+ messageId: 'cssPropWithPragma',
fix(fixer) {
if (hasJsxImport) {
+ /* istanbul ignore if */
+ if (emotionCoreNode === null) {
+ throw new Error(
+ `Unexpected null when attempting to fix ${context.getFilename()} - please file a github issue at ${REPO_URL}`
+ )
+ }
+
return fixer.insertTextBefore(
emotionCoreNode,
`/** @jsx ${local} */\n`
@@ -154,7 +201,9 @@ export default {
emotionCoreNode.specifiers.length - 1
]
- if (lastSpecifier.type === 'ImportDefaultSpecifier') {
+ if (
+ lastSpecifier.type === AST_NODE_TYPES.ImportDefaultSpecifier
+ ) {
return fixer.insertTextAfter(lastSpecifier, ', { jsx }')
}
@@ -174,38 +223,48 @@ export default {
})
return
}
+
+ /* istanbul ignore if */
+ if (emotionCoreNode === null) {
+ throw new Error(
+ `Unexpected null when attempting to fix ${context.getFilename()} - please file a github issue at ${REPO_URL}`
+ )
+ }
+
+ const { specifiers } = emotionCoreNode
+ const { value } = node
+
if (
- node.value.type === 'JSXExpressionContainer' &&
- node.value.expression.type === 'TemplateLiteral'
+ value &&
+ value.type === AST_NODE_TYPES.JSXExpressionContainer &&
+ value.expression.type === AST_NODE_TYPES.TemplateLiteral
) {
- let cssSpecifier = emotionCoreNode.specifiers.find(
- x => x.imported.name === 'css'
+ let cssSpecifier = specifiers.find(
+ x =>
+ x.type === AST_NODE_TYPES.ImportSpecifier &&
+ x.imported.name === 'css'
)
context.report({
node,
- message:
- 'Template literals should be replaced with tagged template literals using `css` when using the css prop',
+ messageId: 'templateLiterals',
fix(fixer) {
if (cssSpecifier) {
return fixer.insertTextBefore(
- node.value.expression,
+ value.expression,
cssSpecifier.local.name
)
}
- let lastSpecifier =
- emotionCoreNode.specifiers[
- emotionCoreNode.specifiers.length - 1
- ]
+ let lastSpecifier = specifiers[specifiers.length - 1]
if (context.getScope().variables.some(x => x.name === 'css')) {
return [
fixer.insertTextAfter(lastSpecifier, `, css as _css`),
- fixer.insertTextBefore(node.value.expression, '_css')
+ fixer.insertTextBefore(value.expression, '_css')
]
}
return [
fixer.insertTextAfter(lastSpecifier, `, css`),
- fixer.insertTextBefore(node.value.expression, 'css')
+ fixer.insertTextBefore(value.expression, 'css')
]
}
})
@@ -213,4 +272,4 @@ export default {
}
}
}
-}
+})
diff --git a/packages/eslint-plugin/src/rules/no-vanilla.js b/packages/eslint-plugin/src/rules/no-vanilla.js
deleted file mode 100644
index 793819576a..0000000000
--- a/packages/eslint-plugin/src/rules/no-vanilla.js
+++ /dev/null
@@ -1,17 +0,0 @@
-export default {
- meta: {
- fixable: 'code'
- },
- create(context) {
- return {
- ImportDeclaration(node) {
- if (node.source.value === '@emotion/css') {
- context.report({
- node: node.source,
- message: `Vanilla emotion should not be used`
- })
- }
- }
- }
- }
-}
diff --git a/packages/eslint-plugin/src/rules/no-vanilla.ts b/packages/eslint-plugin/src/rules/no-vanilla.ts
new file mode 100644
index 0000000000..72b0524757
--- /dev/null
+++ b/packages/eslint-plugin/src/rules/no-vanilla.ts
@@ -0,0 +1,31 @@
+import { createRule } from '../utils'
+
+const messages = {
+ vanillaEmotion: 'Vanilla emotion should not be used'
+}
+
+export default createRule({
+ name: __filename,
+ meta: {
+ docs: {
+ description: 'Ensure vanilla emotion is not used',
+ recommended: false
+ },
+ messages,
+ schema: [],
+ type: 'problem'
+ },
+ defaultOptions: [],
+ create(context) {
+ return {
+ ImportDeclaration(node) {
+ if (node.source.value === '@emotion/css') {
+ context.report({
+ node: node.source,
+ messageId: 'vanillaEmotion'
+ })
+ }
+ }
+ }
+ }
+})
diff --git a/packages/eslint-plugin/src/rules/pkg-renaming.js b/packages/eslint-plugin/src/rules/pkg-renaming.js
deleted file mode 100644
index 2e6dbfaf85..0000000000
--- a/packages/eslint-plugin/src/rules/pkg-renaming.js
+++ /dev/null
@@ -1,67 +0,0 @@
-let simpleMappings = {
- '@emotion/core': '@emotion/react',
- emotion: '@emotion/css',
- 'emotion/macro': '@emotion/css/macro',
- '@emotion/styled-base': '@emotion/styled/base',
- 'jest-emotion': '@emotion/jest',
- 'babel-plugin-emotion': '@emotion/babel-plugin',
- 'eslint-plugin-emotion': '@emotion/eslint-plugin',
- 'create-emotion-server': '@emotion/server/create-instance',
- 'create-emotion': '@emotion/css/create-instance',
- 'emotion-server': '@emotion/server'
-}
-
-export default {
- meta: {
- fixable: 'code'
- },
- create(context) {
- return {
- ImportDeclaration(node) {
- let maybeMapping = simpleMappings[node.source.value]
- if (maybeMapping !== undefined) {
- context.report({
- node: node.source,
- message: `${JSON.stringify(
- node.source.value
- )} has been renamed to ${JSON.stringify(
- maybeMapping
- )}, please import it from ${JSON.stringify(maybeMapping)} instead`,
- fix: fixer => fixer.replaceText(node.source, `'${maybeMapping}'`)
- })
- }
- if (
- (node.source.value === '@emotion/css' ||
- node.source.value === '@emotion/css/macro') &&
- node.specifiers.length === 1 &&
- node.specifiers[0].type === 'ImportDefaultSpecifier'
- ) {
- let replacement =
- node.source.value === '@emotion/css'
- ? '@emotion/react'
- : '@emotion/react/macro'
- context.report({
- node: node.source,
- message: `The default export of "${node.source.value}" in Emotion 10 has been moved to a named export, \`css\`, from "${replacement}" in Emotion 11, please import it from "${replacement}"`,
- fix: fixer =>
- fixer.replaceText(
- node,
- `import { css${
- node.specifiers[0].local.name === 'css'
- ? ''
- : ` as ${node.specifiers[0].local.name}`
- } } from '${replacement}'`
- )
- })
- }
- if (node.source.value === 'emotion-theming') {
- context.report({
- node: node.source,
- message: `"emotion-theming" has been moved into "@emotion/react", please import its exports from "@emotion/react"`,
- fix: fixer => fixer.replaceText(node.source, `'@emotion/react'`)
- })
- }
- }
- }
- }
-}
diff --git a/packages/eslint-plugin/src/rules/pkg-renaming.ts b/packages/eslint-plugin/src/rules/pkg-renaming.ts
new file mode 100644
index 0000000000..9b546015dd
--- /dev/null
+++ b/packages/eslint-plugin/src/rules/pkg-renaming.ts
@@ -0,0 +1,89 @@
+import { AST_NODE_TYPES } from '@typescript-eslint/utils'
+import { createRule } from '../utils'
+
+const simpleMappings = new Map([
+ ['@emotion/core', '@emotion/react'],
+ ['emotion', '@emotion/css'],
+ ['emotion/macro', '@emotion/css/macro'],
+ ['@emotion/styled-base', '@emotion/styled/base'],
+ ['jest-emotion', '@emotion/jest'],
+ ['babel-plugin-emotion', '@emotion/babel-plugin'],
+ ['eslint-plugin-emotion', '@emotion/eslint-plugin'],
+ ['create-emotion-server', '@emotion/server/create-instance'],
+ ['create-emotion', '@emotion/css/create-instance'],
+ ['emotion-server', '@emotion/server']
+])
+
+const messages = {
+ renamePackage: `{{ beforeName }} has been renamed to {{ afterName }}, please import it from {{ afterName }} instead`,
+ exportChange: `The default export of "{{ name }}" in Emotion 10 has been moved to a named export, \`css\`, from "{{ replacement }}" in Emotion 11, please import it from "{{ replacement }}"`,
+ emotionTheming: `"emotion-theming" has been moved into "@emotion/react", please import its exports from "@emotion/react"`
+}
+
+export default createRule({
+ name: __filename,
+ meta: {
+ docs: {
+ description: 'Internal rule',
+ recommended: false
+ },
+ fixable: 'code',
+ messages,
+ schema: [],
+ type: 'problem'
+ },
+ defaultOptions: [],
+ create(context) {
+ return {
+ ImportDeclaration(node) {
+ const maybeMapping = simpleMappings.get(node.source.value)
+ if (maybeMapping !== undefined) {
+ context.report({
+ node: node.source,
+ messageId: 'renamePackage',
+ data: {
+ beforeName: JSON.stringify(node.source.value),
+ afterName: JSON.stringify(maybeMapping)
+ },
+ fix: fixer => fixer.replaceText(node.source, `'${maybeMapping}'`)
+ })
+ }
+ if (
+ (node.source.value === '@emotion/css' ||
+ node.source.value === '@emotion/css/macro') &&
+ node.specifiers.length === 1 &&
+ node.specifiers[0].type === AST_NODE_TYPES.ImportDefaultSpecifier
+ ) {
+ let replacement =
+ node.source.value === '@emotion/css'
+ ? '@emotion/react'
+ : '@emotion/react/macro'
+ context.report({
+ node: node.source,
+ messageId: 'exportChange',
+ data: {
+ name: node.source.value,
+ replacement
+ },
+ fix: fixer =>
+ fixer.replaceText(
+ node,
+ `import { css${
+ node.specifiers[0].local.name === 'css'
+ ? ''
+ : ` as ${node.specifiers[0].local.name}`
+ } } from '${replacement}'`
+ )
+ })
+ }
+ if (node.source.value === 'emotion-theming') {
+ context.report({
+ node: node.source,
+ messageId: 'emotionTheming',
+ fix: fixer => fixer.replaceText(node.source, `'@emotion/react'`)
+ })
+ }
+ }
+ }
+ }
+})
diff --git a/packages/eslint-plugin/src/rules/styled-import.js b/packages/eslint-plugin/src/rules/styled-import.js
deleted file mode 100644
index 89ccf2310a..0000000000
--- a/packages/eslint-plugin/src/rules/styled-import.js
+++ /dev/null
@@ -1,25 +0,0 @@
-export default {
- meta: {
- fixable: 'code'
- },
- create(context) {
- return {
- ImportDeclaration(node) {
- if (node.source.value === 'react-emotion') {
- let newImportPath = '@emotion/styled'
- context.report({
- node: node.source,
- message: `styled should be imported from @emotion/styled`,
- fix:
- node.specifiers.length === 1 &&
- node.specifiers[0].type === 'ImportDefaultSpecifier'
- ? fixer => {
- return fixer.replaceText(node.source, `'${newImportPath}'`)
- }
- : undefined
- })
- }
- }
- }
- }
-}
diff --git a/packages/eslint-plugin/src/rules/styled-import.ts b/packages/eslint-plugin/src/rules/styled-import.ts
new file mode 100644
index 0000000000..e9aeefbbe8
--- /dev/null
+++ b/packages/eslint-plugin/src/rules/styled-import.ts
@@ -0,0 +1,41 @@
+import { AST_NODE_TYPES } from '@typescript-eslint/utils'
+import { createRule } from '../utils'
+
+const messages = {
+ incorrectImport: 'styled should be imported from @emotion/styled'
+}
+
+export default createRule({
+ name: __filename,
+ meta: {
+ docs: {
+ description: 'Ensure styled is imported from @emotion/styled',
+ recommended: false
+ },
+ fixable: 'code',
+ messages,
+ schema: [],
+ type: 'problem'
+ },
+ defaultOptions: [],
+ create(context) {
+ return {
+ ImportDeclaration(node) {
+ if (node.source.value === 'react-emotion') {
+ let newImportPath = '@emotion/styled'
+ context.report({
+ node: node.source,
+ messageId: 'incorrectImport',
+ fix:
+ node.specifiers.length === 1 &&
+ node.specifiers[0].type === AST_NODE_TYPES.ImportDefaultSpecifier
+ ? fixer => {
+ return fixer.replaceText(node.source, `'${newImportPath}'`)
+ }
+ : undefined
+ })
+ }
+ }
+ }
+ }
+})
diff --git a/packages/eslint-plugin/src/rules/syntax-preference.js b/packages/eslint-plugin/src/rules/syntax-preference.ts
similarity index 55%
rename from packages/eslint-plugin/src/rules/syntax-preference.js
rename to packages/eslint-plugin/src/rules/syntax-preference.ts
index 891713a879..7568eb805b 100644
--- a/packages/eslint-plugin/src/rules/syntax-preference.js
+++ b/packages/eslint-plugin/src/rules/syntax-preference.ts
@@ -1,16 +1,20 @@
+import { AST_NODE_TYPES, TSESLint, TSESTree } from '@typescript-eslint/utils'
+import { createRule } from '../utils'
+
/**
* @fileoverview Choose between string or object syntax
* @author alex-pex
*/
-function isStringStyle(node) {
- if (node.tag.type === 'Identifier' && node.tag.name === 'css') {
+function isStringStyle(node: TSESTree.TaggedTemplateExpression) {
+ if (node.tag.type === AST_NODE_TYPES.Identifier && node.tag.name === 'css') {
return true
}
// shorthand notation
// eg: styled.h1` color: red; `
if (
- node.tag.type === 'MemberExpression' &&
+ node.tag.type === AST_NODE_TYPES.MemberExpression &&
+ node.tag.object.type === AST_NODE_TYPES.Identifier &&
node.tag.object.name === 'styled'
) {
// string syntax used
@@ -19,7 +23,11 @@ function isStringStyle(node) {
// full notation
// eg: styled('h1')` color: red; `
- if (node.tag.type === 'CallExpression' && node.tag.callee.name === 'styled') {
+ if (
+ node.tag.type === AST_NODE_TYPES.CallExpression &&
+ node.tag.callee.type === AST_NODE_TYPES.Identifier &&
+ node.tag.callee.name === 'styled'
+ ) {
// string syntax used
return true
}
@@ -27,15 +35,19 @@ function isStringStyle(node) {
return false
}
-function isObjectStyle(node) {
- if (node.callee.type === 'Identifier' && node.callee.name === 'css') {
+function isObjectStyle(node: TSESTree.CallExpression) {
+ if (
+ node.callee.type === AST_NODE_TYPES.Identifier &&
+ node.callee.name === 'css'
+ ) {
return true
}
// shorthand notation
// eg: styled.h1({ color: 'red' })
if (
- node.callee.type === 'MemberExpression' &&
+ node.callee.type === AST_NODE_TYPES.MemberExpression &&
+ node.callee.object.type === AST_NODE_TYPES.Identifier &&
node.callee.object.name === 'styled'
) {
// object syntax used
@@ -45,7 +57,8 @@ function isObjectStyle(node) {
// full notation
// eg: styled('h1')({ color: 'red' })
if (
- node.callee.type === 'CallExpression' &&
+ node.callee.type === AST_NODE_TYPES.CallExpression &&
+ node.callee.callee.type === AST_NODE_TYPES.Identifier &&
node.callee.callee.name === 'styled'
) {
// object syntax used
@@ -59,42 +72,42 @@ function isObjectStyle(node) {
// Rule Definition
// ------------------------------------------------------------------------------
-const MSG_PREFER_STRING_STYLE = 'Styles should be written using strings.'
-const MSG_PREFER_OBJECT_STYLE = 'Styles should be written using objects.'
-const MSG_PREFER_WRAPPING_WITH_CSS =
- 'Prefer wrapping your string styles with `css` call.'
-
-const checkExpressionPreferringObject = (context, node) => {
+const checkExpressionPreferringObject = (
+ context: RuleContext,
+ node: TSESTree.Node
+) => {
switch (node.type) {
- case 'ArrayExpression':
+ case AST_NODE_TYPES.ArrayExpression:
node.elements.forEach(element =>
checkExpressionPreferringObject(context, element)
)
return
- case 'TemplateLiteral':
+ case AST_NODE_TYPES.TemplateLiteral:
context.report({
node,
- message: MSG_PREFER_OBJECT_STYLE
+ messageId: 'preferObjectStyle'
})
return
- case 'Literal':
+ case AST_NODE_TYPES.Literal:
// validating other literal types seems out of scope of this plugin
if (typeof node.value !== 'string') {
return
}
context.report({
node,
- message: MSG_PREFER_OBJECT_STYLE
+ messageId: 'preferObjectStyle'
})
}
}
-const createPreferredObjectVisitor = context => ({
+const createPreferredObjectVisitor = (
+ context: RuleContext
+): TSESLint.RuleListener => ({
TaggedTemplateExpression(node) {
if (isStringStyle(node)) {
context.report({
node,
- message: MSG_PREFER_OBJECT_STYLE
+ messageId: 'preferObjectStyle'
})
}
},
@@ -110,24 +123,35 @@ const createPreferredObjectVisitor = context => ({
return
}
+ if (!node.value) {
+ context.report({
+ node: node,
+ messageId: 'emptyCssProp'
+ })
+ return
+ }
+
switch (node.value.type) {
- case 'Literal':
+ case AST_NODE_TYPES.Literal:
// validating other literal types seems out of scope of this plugin
if (typeof node.value.value !== 'string') {
return
}
context.report({
node: node.value,
- message: MSG_PREFER_OBJECT_STYLE
+ messageId: 'preferObjectStyle'
})
return
- case 'JSXExpressionContainer':
+ case AST_NODE_TYPES.JSXExpressionContainer:
checkExpressionPreferringObject(context, node.value.expression)
}
}
})
-const checkExpressionPreferringString = (context, node) => {
+const checkExpressionPreferringString = (
+ context: RuleContext,
+ node: TSESTree.Node
+) => {
switch (node.type) {
case 'ArrayExpression':
node.elements.forEach(element =>
@@ -137,7 +161,7 @@ const checkExpressionPreferringString = (context, node) => {
case 'ObjectExpression':
context.report({
node,
- message: MSG_PREFER_STRING_STYLE
+ messageId: 'preferStringStyle'
})
return
case 'Literal':
@@ -147,12 +171,14 @@ const checkExpressionPreferringString = (context, node) => {
}
context.report({
node,
- message: MSG_PREFER_WRAPPING_WITH_CSS
+ messageId: 'preferWrappingWithCSS'
})
}
}
-const createPreferredStringVisitor = context => ({
+const createPreferredStringVisitor = (
+ context: RuleContext
+): TSESLint.RuleListener => ({
CallExpression(node) {
if (isObjectStyle(node)) {
node.arguments.forEach(argument =>
@@ -166,38 +192,62 @@ const createPreferredStringVisitor = context => ({
return
}
+ if (!node.value) {
+ context.report({
+ node: node,
+ messageId: 'emptyCssProp'
+ })
+ return
+ }
+
switch (node.value.type) {
- case 'Literal':
+ case AST_NODE_TYPES.Literal:
// validating other literal types seems out of scope of this plugin
if (typeof node.value.value !== 'string') {
return
}
context.report({
node: node.value,
- message: MSG_PREFER_WRAPPING_WITH_CSS
+ messageId: 'preferWrappingWithCSS'
})
return
- case 'JSXExpressionContainer':
+ case AST_NODE_TYPES.JSXExpressionContainer:
checkExpressionPreferringString(context, node.value.expression)
}
}
})
-export default {
+type RuleOptions = [('string' | 'object')?]
+
+type MessageId =
+ | 'preferStringStyle'
+ | 'preferObjectStyle'
+ | 'preferWrappingWithCSS'
+ | 'emptyCssProp'
+
+type RuleContext = TSESLint.RuleContext
+
+export default createRule({
+ name: __filename,
meta: {
docs: {
- description: 'Choose between string or object styles',
- category: 'Stylistic Issues',
+ description: 'Choose between styles written as strings or objects',
recommended: false
},
- fixable: null, // or "code" or "whitespace"
+ messages: {
+ preferStringStyle: 'Styles should be written using strings.',
+ preferObjectStyle: 'Styles should be written using objects.',
+ preferWrappingWithCSS: `Prefer wrapping your string styles with \`css\` call.`,
+ emptyCssProp: `Empty \`css\` prop is not valid.`
+ },
schema: [
{
enum: ['string', 'object']
}
- ]
+ ],
+ type: 'problem'
},
-
+ defaultOptions: [],
create(context) {
const preferredSyntax = context.options[0]
@@ -210,4 +260,4 @@ export default {
return {}
}
}
-}
+})
diff --git a/packages/eslint-plugin/src/utils.ts b/packages/eslint-plugin/src/utils.ts
new file mode 100644
index 0000000000..7fbef3077c
--- /dev/null
+++ b/packages/eslint-plugin/src/utils.ts
@@ -0,0 +1,12 @@
+import { ESLintUtils } from '@typescript-eslint/utils'
+import { parse as parsePath } from 'path'
+
+const { version } = require('../package.json')
+
+export const REPO_URL = 'https://github.com/emotion-js/emotion'
+
+export const createRule = ESLintUtils.RuleCreator(name => {
+ const ruleName = parsePath(name).name
+
+ return `${REPO_URL}/blob/@emotion/eslint-plugin@${version}/packages/eslint-plugin/docs/rules/${ruleName}.md`
+})
diff --git a/packages/eslint-plugin/test/rules/import-from-emotion.test.js b/packages/eslint-plugin/test/rules/import-from-emotion.test.ts
similarity index 60%
rename from packages/eslint-plugin/test/rules/import-from-emotion.test.js
rename to packages/eslint-plugin/test/rules/import-from-emotion.test.ts
index b28f99730d..99be3a0fa0 100644
--- a/packages/eslint-plugin/test/rules/import-from-emotion.test.js
+++ b/packages/eslint-plugin/test/rules/import-from-emotion.test.ts
@@ -2,12 +2,12 @@
* @jest-environment node
*/
-import { RuleTester } from 'eslint'
-import { rules as emotionRules } from '@emotion/eslint-plugin'
+import { TSESLint } from '@typescript-eslint/utils'
+import rule from '../../src/rules/import-from-emotion'
+import { espreeParser } from '../test-utils'
-const rule = emotionRules['import-from-emotion']
-
-RuleTester.setDefaultConfig({
+const ruleTester = new TSESLint.RuleTester({
+ parser: espreeParser,
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
@@ -17,8 +17,6 @@ RuleTester.setDefaultConfig({
}
})
-const ruleTester = new RuleTester()
-
ruleTester.run('emotion jsx', rule, {
valid: [
{
@@ -31,8 +29,7 @@ ruleTester.run('emotion jsx', rule, {
code: `import { css } from 'react-emotion'`,
errors: [
{
- message:
- "emotion's exports should be imported directly from emotion rather than from react-emotion"
+ messageId: 'incorrectImport'
}
],
output: `import { css } from 'emotion'`
@@ -41,8 +38,7 @@ ruleTester.run('emotion jsx', rule, {
code: `import styled, { css } from 'react-emotion'`,
errors: [
{
- message:
- "emotion's exports should be imported directly from emotion rather than from react-emotion"
+ messageId: 'incorrectImport'
}
],
output: `import styled from '@emotion/styled';\nimport { css } from 'emotion';`
@@ -51,8 +47,7 @@ ruleTester.run('emotion jsx', rule, {
code: `import styled, { css as somethingElse } from 'react-emotion'`,
errors: [
{
- message:
- "emotion's exports should be imported directly from emotion rather than from react-emotion"
+ messageId: 'incorrectImport'
}
],
output: `import styled from '@emotion/styled';\nimport { css as somethingElse } from 'emotion';`
diff --git a/packages/eslint-plugin/test/rules/jsx-import.test.js b/packages/eslint-plugin/test/rules/jsx-import.test.ts
similarity index 71%
rename from packages/eslint-plugin/test/rules/jsx-import.test.js
rename to packages/eslint-plugin/test/rules/jsx-import.test.ts
index 6a0fa0b793..f245357e64 100644
--- a/packages/eslint-plugin/test/rules/jsx-import.test.js
+++ b/packages/eslint-plugin/test/rules/jsx-import.test.ts
@@ -2,12 +2,12 @@
* @jest-environment node
*/
-import { RuleTester } from 'eslint'
-import { rules as emotionRules } from '@emotion/eslint-plugin'
+import { TSESLint } from '@typescript-eslint/utils'
+import rule from '../../src/rules/jsx-import'
+import { espreeParser } from '../test-utils'
-const rule = emotionRules['jsx-import']
-
-RuleTester.setDefaultConfig({
+const ruleTester = new TSESLint.RuleTester({
+ parser: espreeParser,
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
@@ -17,8 +17,6 @@ RuleTester.setDefaultConfig({
}
})
-const ruleTester = new RuleTester()
-
ruleTester.run('emotion jsx', rule, {
valid: [
{
@@ -73,6 +71,14 @@ ruleTester.run('emotion jsx', rule, {
let ele =
`
+ },
+ {
+ code: `
+ /** @jsx jsx */
+ import {jsx} from '@emotion/react'
+ // it's invalid but not for this rule
+ let ele =
+ `
}
],
@@ -84,8 +90,7 @@ let ele =
`.trim(),
errors: [
{
- message:
- 'The css prop can only be used if jsx from @emotion/react is imported and it is set as the jsx pragma'
+ messageId: 'cssPropWithPragma'
}
],
output: `
@@ -101,8 +106,8 @@ let ele =
`.trim(),
errors: [
{
- message:
- 'The css prop can only be used if jsxImportSource is set to @emotion/react'
+ messageId: 'cssProp',
+ data: { importSource: '@emotion/react' }
}
],
output: `
@@ -117,8 +122,8 @@ let ele =
`.trim(),
errors: [
{
- message:
- 'The css prop can only be used if jsxImportSource is set to @iChenLei/react'
+ messageId: 'cssProp',
+ data: { importSource: '@iChenLei/react' }
}
],
output: `
@@ -134,8 +139,8 @@ let ele =
`.trim(),
errors: [
{
- message:
- 'The css prop can only be used if jsxImportSource is set to @iChenLei/react'
+ messageId: 'cssProp',
+ data: { importSource: '@iChenLei/react' }
}
],
output: `
@@ -150,8 +155,7 @@ let ele =
`.trim(),
errors: [
{
- message:
- 'The css prop can only be used if jsx from @emotion/react is imported and it is set as the jsx pragma'
+ messageId: 'cssPropWithPragma'
}
],
output: `
@@ -168,8 +172,7 @@ let ele =
`.trim(),
errors: [
{
- message:
- 'The css prop can only be used if jsx from @emotion/react is imported and it is set as the jsx pragma'
+ messageId: 'cssPropWithPragma'
}
],
output: `
@@ -186,8 +189,7 @@ let ele =
`.trim(),
errors: [
{
- message:
- 'The css prop can only be used if jsx from @emotion/react is imported and it is set as the jsx pragma'
+ messageId: 'cssPropWithPragma'
}
],
output: `
@@ -203,8 +205,7 @@ let ele =
`.trim(),
errors: [
{
- message:
- 'The css prop can only be used if jsx from @emotion/react is imported and it is set as the jsx pragma'
+ messageId: 'cssPropWithPragma'
}
],
output: `
@@ -219,8 +220,7 @@ let ele =
`.trim(),
errors: [
{
- message:
- 'The css prop can only be used if jsx from @emotion/react is imported and it is set as the jsx pragma'
+ messageId: 'cssPropWithPragma'
}
],
output: `
@@ -231,13 +231,30 @@ let ele =
},
{
code: `
+/** @jsx jsx */
+import * as emotion from '@emotion/react'
+let ele =
+ `.trim(),
+ errors: [
+ {
+ messageId: 'cssPropWithPragma'
+ }
+ ],
+ output: `
+/** @jsx jsx */
+/** @jsx emotion.jsx */
+import * as emotion from '@emotion/react'
+let ele =
+ `.trim()
+ },
+ {
+ code: `
import {jsx} from '@emotion/react'
let ele =
`.trim(),
errors: [
{
- message:
- 'The css prop can only be used if jsx from @emotion/react is imported and it is set as the jsx pragma'
+ messageId: 'cssPropWithPragma'
}
],
output: `
@@ -254,12 +271,10 @@ let ele2 =
`.trim(),
errors: [
{
- message:
- 'The css prop can only be used if jsx from @emotion/react is imported and it is set as the jsx pragma'
+ messageId: 'cssPropWithPragma'
},
{
- message:
- 'The css prop can only be used if jsx from @emotion/react is imported and it is set as the jsx pragma'
+ messageId: 'cssPropWithPragma'
}
],
output: `
@@ -278,8 +293,7 @@ let ele2 =
`.trim(),
errors: [
{
- message:
- 'Template literals should be replaced with tagged template literals using `css` when using the css prop'
+ messageId: 'templateLiterals'
}
],
output: `
@@ -297,8 +311,7 @@ let ele2 =
`.trim(),
errors: [
{
- message:
- 'Template literals should be replaced with tagged template literals using `css` when using the css prop'
+ messageId: 'templateLiterals'
}
],
output: `
@@ -316,8 +329,7 @@ let ele2 =
`.trim(),
errors: [
{
- message:
- 'Template literals should be replaced with tagged template literals using `css` when using the css prop'
+ messageId: 'templateLiterals'
}
],
output: `
diff --git a/packages/eslint-plugin/test/rules/no-vanilla.test.js b/packages/eslint-plugin/test/rules/no-vanilla.test.ts
similarity index 58%
rename from packages/eslint-plugin/test/rules/no-vanilla.test.js
rename to packages/eslint-plugin/test/rules/no-vanilla.test.ts
index cb77156431..a897ec3a70 100644
--- a/packages/eslint-plugin/test/rules/no-vanilla.test.js
+++ b/packages/eslint-plugin/test/rules/no-vanilla.test.ts
@@ -2,12 +2,12 @@
* @jest-environment node
*/
-import { RuleTester } from 'eslint'
-import { rules as emotionRules } from '@emotion/eslint-plugin'
+import { TSESLint } from '@typescript-eslint/utils'
+import rule from '../../src/rules/no-vanilla'
+import { espreeParser } from '../test-utils'
-const rule = emotionRules['no-vanilla']
-
-RuleTester.setDefaultConfig({
+const ruleTester = new TSESLint.RuleTester({
+ parser: espreeParser,
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
@@ -17,8 +17,6 @@ RuleTester.setDefaultConfig({
}
})
-const ruleTester = new RuleTester()
-
ruleTester.run('no-vanilla', rule, {
valid: [{ code: `import { css } from '@emotion/react'` }],
invalid: [
@@ -26,7 +24,7 @@ ruleTester.run('no-vanilla', rule, {
code: `import { css } from '@emotion/css'`,
errors: [
{
- message: `Vanilla emotion should not be used`
+ messageId: 'vanillaEmotion'
}
]
}
diff --git a/packages/eslint-plugin/test/rules/pkg-renaming.test.js b/packages/eslint-plugin/test/rules/pkg-renaming.test.ts
similarity index 53%
rename from packages/eslint-plugin/test/rules/pkg-renaming.test.js
rename to packages/eslint-plugin/test/rules/pkg-renaming.test.ts
index 0377b13ee4..6e7093212e 100644
--- a/packages/eslint-plugin/test/rules/pkg-renaming.test.js
+++ b/packages/eslint-plugin/test/rules/pkg-renaming.test.ts
@@ -2,10 +2,12 @@
* @jest-environment node
*/
-const { RuleTester } = require('eslint')
-const rule = require('@emotion/eslint-plugin').rules['pkg-renaming']
+import { TSESLint } from '@typescript-eslint/utils'
+import rule from '../../src/rules/pkg-renaming'
+import { espreeParser } from '../test-utils'
-RuleTester.setDefaultConfig({
+const ruleTester = new TSESLint.RuleTester({
+ parser: espreeParser,
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
@@ -15,8 +17,6 @@ RuleTester.setDefaultConfig({
}
})
-const ruleTester = new RuleTester()
-
ruleTester.run('pkg-renaming', rule, {
valid: [
{
@@ -31,8 +31,11 @@ ruleTester.run('pkg-renaming', rule, {
code: `import { css } from 'emotion'`,
errors: [
{
- message:
- '"emotion" has been renamed to "@emotion/css", please import it from "@emotion/css" instead'
+ messageId: 'renamePackage',
+ data: {
+ beforeName: '"emotion"',
+ afterName: '"@emotion/css"'
+ }
}
],
output: `import { css } from '@emotion/css'`
@@ -41,8 +44,11 @@ ruleTester.run('pkg-renaming', rule, {
code: `import { css } from '@emotion/core'`,
errors: [
{
- message:
- '"@emotion/core" has been renamed to "@emotion/react", please import it from "@emotion/react" instead'
+ messageId: 'renamePackage',
+ data: {
+ beforeName: '"@emotion/core"',
+ afterName: '"@emotion/react"'
+ }
}
],
output: `import { css } from '@emotion/react'`
@@ -51,8 +57,11 @@ ruleTester.run('pkg-renaming', rule, {
code: `import css from '@emotion/css'`,
errors: [
{
- message:
- 'The default export of "@emotion/css" in Emotion 10 has been moved to a named export, `css`, from "@emotion/react" in Emotion 11, please import it from "@emotion/react"'
+ messageId: 'exportChange',
+ data: {
+ name: '@emotion/css',
+ replacement: '@emotion/react'
+ }
}
],
output: `import { css } from '@emotion/react'`
@@ -61,8 +70,11 @@ ruleTester.run('pkg-renaming', rule, {
code: `import css from '@emotion/css/macro'`,
errors: [
{
- message:
- 'The default export of "@emotion/css/macro" in Emotion 10 has been moved to a named export, `css`, from "@emotion/react/macro" in Emotion 11, please import it from "@emotion/react/macro"'
+ messageId: 'exportChange',
+ data: {
+ name: '@emotion/css/macro',
+ replacement: '@emotion/react/macro'
+ }
}
],
output: `import { css } from '@emotion/react/macro'`
@@ -71,8 +83,7 @@ ruleTester.run('pkg-renaming', rule, {
code: `import {ThemeProvider, withTheme} from 'emotion-theming'`,
errors: [
{
- message:
- '"emotion-theming" has been moved into "@emotion/react", please import its exports from "@emotion/react"'
+ messageId: 'emotionTheming'
}
],
output: `import {ThemeProvider, withTheme} from '@emotion/react'`
diff --git a/packages/eslint-plugin/test/rules/styled-import.test.js b/packages/eslint-plugin/test/rules/styled-import.test.ts
similarity index 63%
rename from packages/eslint-plugin/test/rules/styled-import.test.js
rename to packages/eslint-plugin/test/rules/styled-import.test.ts
index 4909d2dc73..944053cd46 100644
--- a/packages/eslint-plugin/test/rules/styled-import.test.js
+++ b/packages/eslint-plugin/test/rules/styled-import.test.ts
@@ -2,12 +2,12 @@
* @jest-environment node
*/
-import { RuleTester } from 'eslint'
-import { rules as emotionRules } from '@emotion/eslint-plugin'
+import { TSESLint } from '@typescript-eslint/utils'
+import rule from '../../src/rules/styled-import'
+import { espreeParser } from '../test-utils'
-const rule = emotionRules['styled-import']
-
-RuleTester.setDefaultConfig({
+const ruleTester = new TSESLint.RuleTester({
+ parser: espreeParser,
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
@@ -17,8 +17,6 @@ RuleTester.setDefaultConfig({
}
})
-const ruleTester = new RuleTester()
-
ruleTester.run('emotion styled', rule, {
valid: [
{
@@ -35,7 +33,7 @@ import styled from 'react-emotion'
`.trim(),
errors: [
{
- message: `styled should be imported from @emotion/styled`
+ messageId: 'incorrectImport'
}
],
output: `
diff --git a/packages/eslint-plugin/test/rules/syntax-preference.test.js b/packages/eslint-plugin/test/rules/syntax-preference.test.ts
similarity index 68%
rename from packages/eslint-plugin/test/rules/syntax-preference.test.js
rename to packages/eslint-plugin/test/rules/syntax-preference.test.ts
index 58e2c9d0d1..4ea172d97a 100644
--- a/packages/eslint-plugin/test/rules/syntax-preference.test.js
+++ b/packages/eslint-plugin/test/rules/syntax-preference.test.ts
@@ -8,12 +8,12 @@
// Requirements
// ------------------------------------------------------------------------------
-import { RuleTester } from 'eslint'
-import { rules as emotionRules } from '@emotion/eslint-plugin'
+import { AST_NODE_TYPES, TSESLint } from '@typescript-eslint/utils'
+import rule from '../../src/rules/syntax-preference'
+import { espreeParser } from '../test-utils'
-const rule = emotionRules['syntax-preference']
-
-RuleTester.setDefaultConfig({
+const ruleTester = new TSESLint.RuleTester({
+ parser: espreeParser,
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
@@ -27,8 +27,6 @@ RuleTester.setDefaultConfig({
// Tests
// ------------------------------------------------------------------------------
-const ruleTester = new RuleTester()
-
ruleTester.run('syntax-preference (string)', rule, {
valid: [
// give me some code that won't trigger a warning
@@ -68,8 +66,8 @@ ruleTester.run('syntax-preference (string)', rule, {
options: ['string'],
errors: [
{
- message: 'Styles should be written using strings.',
- type: 'ObjectExpression'
+ messageId: 'preferStringStyle',
+ type: AST_NODE_TYPES.ObjectExpression
}
]
},
@@ -78,8 +76,8 @@ ruleTester.run('syntax-preference (string)', rule, {
options: ['string'],
errors: [
{
- message: 'Styles should be written using strings.',
- type: 'ObjectExpression'
+ messageId: 'preferStringStyle',
+ type: AST_NODE_TYPES.ObjectExpression
}
]
},
@@ -88,8 +86,8 @@ ruleTester.run('syntax-preference (string)', rule, {
options: ['string'],
errors: [
{
- message: 'Styles should be written using strings.',
- type: 'ObjectExpression'
+ messageId: 'preferStringStyle',
+ type: AST_NODE_TYPES.ObjectExpression
}
]
},
@@ -98,8 +96,8 @@ ruleTester.run('syntax-preference (string)', rule, {
options: ['string'],
errors: [
{
- message: 'Prefer wrapping your string styles with `css` call.',
- type: 'Literal'
+ messageId: 'preferWrappingWithCSS',
+ type: AST_NODE_TYPES.Literal
}
]
},
@@ -108,8 +106,8 @@ ruleTester.run('syntax-preference (string)', rule, {
options: ['string'],
errors: [
{
- message: 'Prefer wrapping your string styles with `css` call.',
- type: 'Literal'
+ messageId: 'preferWrappingWithCSS',
+ type: AST_NODE_TYPES.Literal
}
]
},
@@ -118,12 +116,12 @@ ruleTester.run('syntax-preference (string)', rule, {
options: ['string'],
errors: [
{
- message: 'Prefer wrapping your string styles with `css` call.',
- type: 'Literal'
+ messageId: 'preferWrappingWithCSS',
+ type: AST_NODE_TYPES.Literal
},
{
- message: 'Styles should be written using strings.',
- type: 'ObjectExpression'
+ messageId: 'preferStringStyle',
+ type: AST_NODE_TYPES.ObjectExpression
}
]
},
@@ -132,8 +130,18 @@ ruleTester.run('syntax-preference (string)', rule, {
options: ['string'],
errors: [
{
- message: 'Styles should be written using strings.',
- type: 'ObjectExpression'
+ messageId: 'preferStringStyle',
+ type: AST_NODE_TYPES.ObjectExpression
+ }
+ ]
+ },
+ {
+ code: `const Foo = () =>
`,
+ options: ['string'],
+ errors: [
+ {
+ messageId: 'emptyCssProp',
+ type: AST_NODE_TYPES.JSXAttribute
}
]
}
@@ -171,8 +179,8 @@ ruleTester.run('syntax-preference (object)', rule, {
options: ['object'],
errors: [
{
- message: 'Styles should be written using objects.',
- type: 'TaggedTemplateExpression'
+ messageId: 'preferObjectStyle',
+ type: AST_NODE_TYPES.TaggedTemplateExpression
}
]
},
@@ -181,8 +189,8 @@ ruleTester.run('syntax-preference (object)', rule, {
options: ['object'],
errors: [
{
- message: 'Styles should be written using objects.',
- type: 'TaggedTemplateExpression'
+ messageId: 'preferObjectStyle',
+ type: AST_NODE_TYPES.TaggedTemplateExpression
}
]
},
@@ -191,8 +199,8 @@ ruleTester.run('syntax-preference (object)', rule, {
options: ['object'],
errors: [
{
- message: 'Styles should be written using objects.',
- type: 'TaggedTemplateExpression'
+ messageId: 'preferObjectStyle',
+ type: AST_NODE_TYPES.TaggedTemplateExpression
}
]
},
@@ -201,8 +209,8 @@ ruleTester.run('syntax-preference (object)', rule, {
options: ['object'],
errors: [
{
- message: 'Styles should be written using objects.',
- type: 'Literal'
+ messageId: 'preferObjectStyle',
+ type: AST_NODE_TYPES.Literal
}
]
},
@@ -211,8 +219,8 @@ ruleTester.run('syntax-preference (object)', rule, {
options: ['object'],
errors: [
{
- message: 'Styles should be written using objects.',
- type: 'Literal'
+ messageId: 'preferObjectStyle',
+ type: AST_NODE_TYPES.Literal
}
]
},
@@ -221,12 +229,12 @@ ruleTester.run('syntax-preference (object)', rule, {
options: ['object'],
errors: [
{
- message: 'Styles should be written using objects.',
- type: 'Literal'
+ messageId: 'preferObjectStyle',
+ type: AST_NODE_TYPES.Literal
},
{
- message: 'Styles should be written using objects.',
- type: 'TaggedTemplateExpression'
+ messageId: 'preferObjectStyle',
+ type: AST_NODE_TYPES.TaggedTemplateExpression
}
]
},
@@ -235,12 +243,22 @@ ruleTester.run('syntax-preference (object)', rule, {
options: ['object'],
errors: [
{
- message: 'Styles should be written using objects.',
- type: 'Literal'
+ messageId: 'preferObjectStyle',
+ type: AST_NODE_TYPES.Literal
},
{
- message: 'Styles should be written using objects.',
- type: 'TaggedTemplateExpression'
+ messageId: 'preferObjectStyle',
+ type: AST_NODE_TYPES.TaggedTemplateExpression
+ }
+ ]
+ },
+ {
+ code: `const Foo = () =>
`,
+ options: ['object'],
+ errors: [
+ {
+ messageId: 'emptyCssProp',
+ type: AST_NODE_TYPES.JSXAttribute
}
]
}
diff --git a/packages/eslint-plugin/test/test-utils.ts b/packages/eslint-plugin/test/test-utils.ts
new file mode 100644
index 0000000000..551a54e9db
--- /dev/null
+++ b/packages/eslint-plugin/test/test-utils.ts
@@ -0,0 +1,6 @@
+import resolveFrom from 'resolve-from'
+
+export const espreeParser: string = resolveFrom(
+ require.resolve('eslint'),
+ 'espree'
+)
diff --git a/packages/hash/package.json b/packages/hash/package.json
index c22396e494..782efc7486 100644
--- a/packages/hash/package.json
+++ b/packages/hash/package.json
@@ -4,13 +4,12 @@
"description": "A MurmurHash2 implementation",
"main": "dist/emotion-hash.cjs.js",
"module": "dist/emotion-hash.esm.js",
- "types": "types/index.d.ts",
+ "types": "dist/emotion-hash.cjs.d.ts",
"license": "MIT",
"repository": "https://github.com/emotion-js/emotion/tree/main/packages/hash",
"files": [
"src",
- "dist",
- "types/*.d.ts"
+ "dist"
],
"scripts": {
"test:typescript": "dtslint types"
diff --git a/packages/hash/src/index.d.ts b/packages/hash/src/index.d.ts
deleted file mode 100644
index 9e46093759..0000000000
--- a/packages/hash/src/index.d.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from '../types'
-export { default } from '../types'
diff --git a/packages/hash/src/index.js b/packages/hash/src/index.ts
similarity index 96%
rename from packages/hash/src/index.js
rename to packages/hash/src/index.ts
index dacf52f904..c7d19839e7 100644
--- a/packages/hash/src/index.js
+++ b/packages/hash/src/index.ts
@@ -1,9 +1,8 @@
-// @flow
/* eslint-disable */
// Inspired by https://github.com/garycourt/murmurhash-js
// Ported from https://github.com/aappleby/smhasher/blob/61a0530f28277f2e850bfc39600ce61d02b518de/src/MurmurHash2.cpp#L37-L86
-export default function murmur2(str: string) {
+export default function murmur2(str: string): string {
// 'm' and 'r' are mixing constants generated offline.
// They're not really 'magic', they just happen to work well.
diff --git a/packages/hash/types/index.d.ts b/packages/hash/types/index.d.ts
index 872aa0beff..2c736dff8d 100644
--- a/packages/hash/types/index.d.ts
+++ b/packages/hash/types/index.d.ts
@@ -1 +1 @@
-export default function murmurhash2_32_gc(str: string): string
+export { default } from '..'
diff --git a/packages/is-prop-valid/package.json b/packages/is-prop-valid/package.json
index e5f5991960..370aed2872 100644
--- a/packages/is-prop-valid/package.json
+++ b/packages/is-prop-valid/package.json
@@ -4,7 +4,7 @@
"description": "A function to check whether a prop is valid for HTML and SVG elements",
"main": "dist/emotion-is-prop-valid.cjs.js",
"module": "dist/emotion-is-prop-valid.esm.js",
- "types": "types/index.d.ts",
+ "types": "dist/emotion-is-prop-valid.cjs.d.ts",
"license": "MIT",
"repository": "https://github.com/emotion-js/emotion/tree/main/packages/is-prop-valid",
"scripts": {
@@ -22,8 +22,7 @@
},
"files": [
"src",
- "dist",
- "types/*.d.ts"
+ "dist"
],
"exports": {
".": {
diff --git a/packages/is-prop-valid/src/index.d.ts b/packages/is-prop-valid/src/index.d.ts
deleted file mode 100644
index 9e46093759..0000000000
--- a/packages/is-prop-valid/src/index.d.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from '../types'
-export { default } from '../types'
diff --git a/packages/is-prop-valid/src/index.js b/packages/is-prop-valid/src/index.ts
similarity index 69%
rename from packages/is-prop-valid/src/index.js
rename to packages/is-prop-valid/src/index.ts
index 9763a339e7..88fb415329 100644
--- a/packages/is-prop-valid/src/index.js
+++ b/packages/is-prop-valid/src/index.ts
@@ -1,9 +1,9 @@
-// @flow
import memoize from '@emotion/memoize'
-declare var codegen: { require: string => RegExp }
+declare const codegen: { require: (path: string) => any }
-const reactPropsRegex = codegen.require('./props')
+// eslint-disable-next-line no-undef
+const reactPropsRegex: RegExp = codegen.require('./props')
// https://esbench.com/bench/5bfee68a4cd7e6009ef61d23
const isPropValid = /* #__PURE__ */ memoize(
diff --git a/packages/is-prop-valid/src/props.js b/packages/is-prop-valid/src/props.js
index d93c7022c7..2dccc9b9a4 100644
--- a/packages/is-prop-valid/src/props.js
+++ b/packages/is-prop-valid/src/props.js
@@ -1,4 +1,6 @@
-// @flow
+/**
+ * This module needs to remain pure JavaScript for codegen to work on it
+ */
const props = {
// react props
// https://github.com/facebook/react/blob/5495a7f24aef85ba6937truetrue1ce962673ca9f5fde6/src/renderers/dom/shared/hooks/ReactDOMUnknownPropertyHook.js
@@ -490,7 +492,6 @@ const props = {
class: true,
autofocus: true
}
-// eslint-disable-next-line import/no-commonjs
module.exports = `/^((${Object.keys(props).join(
'|'
)})|(([Dd][Aa][Tt][Aa]|[Aa][Rr][Ii][Aa]|x)-.*))$/`
diff --git a/packages/is-prop-valid/types/index.d.ts b/packages/is-prop-valid/types/index.d.ts
index e7d00bfdbf..5f85d28f68 100644
--- a/packages/is-prop-valid/types/index.d.ts
+++ b/packages/is-prop-valid/types/index.d.ts
@@ -1,5 +1,3 @@
-// Definitions by: Junyoung Clare Jang
// TypeScript Version: 2.1
-declare function isPropValid(prop: string): boolean
-export default isPropValid
+export { default } from '..'
diff --git a/packages/is-prop-valid/types/tslint.json b/packages/is-prop-valid/types/tslint.json
index cd0be207a3..4326a0372b 100644
--- a/packages/is-prop-valid/types/tslint.json
+++ b/packages/is-prop-valid/types/tslint.json
@@ -17,6 +17,7 @@
"check-preblock"
],
- "no-unnecessary-generics": false
+ "no-unnecessary-generics": false,
+ "no-default-import": false
}
}
diff --git a/packages/jest/src/create-enzyme-serializer.js b/packages/jest/src/create-enzyme-serializer.js
index c91d440922..2178056037 100644
--- a/packages/jest/src/create-enzyme-serializer.js
+++ b/packages/jest/src/create-enzyme-serializer.js
@@ -1,5 +1,4 @@
-// @flow
-import type { Options } from './create-serializer'
+/* import type { Options } from './create-serializer' */
import { createSerializer as createEmotionSerializer } from './create-serializer'
import * as enzymeTickler from './enzyme-tickler'
import { createSerializer as createEnzymeToJsonSerializer } from 'enzyme-to-json'
@@ -68,23 +67,23 @@ export function createEnzymeSerializer({
classNameReplacer,
DOMElements = true,
includeStyles = true
-}: Options = {}) {
+} /* : Options */ = {}) {
const emotionSerializer = createEmotionSerializer({
classNameReplacer,
DOMElements,
includeStyles
})
return {
- test(node: *) {
+ test(node) {
return wrappedEnzymeSerializer.test(node) || emotionSerializer.test(node)
},
serialize(
- node: *,
- config: *,
- indentation: string,
- depth: number,
- refs: *,
- printer: Function
+ node,
+ config,
+ indentation /*: string */,
+ depth /*: number */,
+ refs,
+ printer /*: Function */
) {
if (wrappedEnzymeSerializer.test(node)) {
const tickled = enzymeTickler.tickle(node)
diff --git a/packages/jest/src/create-serializer.js b/packages/jest/src/create-serializer.js
index c1c5795bb6..533b7ecf0c 100644
--- a/packages/jest/src/create-serializer.js
+++ b/packages/jest/src/create-serializer.js
@@ -1,4 +1,3 @@
-// @flow
import prettify from '@emotion/css-prettifier'
import { replaceClassNames } from './replace-class-names'
import * as enzymeTickler from './enzyme-tickler'
@@ -49,13 +48,13 @@ function deepTransform(node, transform) {
return node.map(child => deepTransform(child, transform))
}
- const transformed: any = transform(node)
+ const transformed = transform(node)
if (transformed !== node && transformed.children) {
return copyProps(transformed, {
// flatMap to allow a child of to be transformed to
children: flatMap(
- (deepTransform(transformed.children, transform): any),
+ deepTransform(transformed.children, transform),
id => id
)
})
@@ -65,18 +64,20 @@ function deepTransform(node, transform) {
}
function getPrettyStylesFromClassNames(
- classNames: Array,
- elements: Array,
- indentation: string
+ classNames /*: Array */,
+ elements /*: Array */,
+ indentation /*: string */
) {
return prettify(getStylesFromClassNames(classNames, elements), indentation)
}
+/*
export type Options = {
classNameReplacer?: (className: string, index: number) => string,
DOMElements?: boolean,
includeStyles?: boolean
}
+*/
function filterEmotionProps(props = {}) {
const {
@@ -102,9 +103,9 @@ function getLabelsFromClassName(keys, className) {
}
function isShallowEnzymeElement(
- element: any,
- keys: string[],
- labels: string[]
+ element /*: any */,
+ keys /*: string[] */,
+ labels /*: string[] */
) {
const childClassNames = (element.children || [])
.map(({ props = {} }) => props.className || '')
@@ -116,47 +117,48 @@ function isShallowEnzymeElement(
})
}
-const createConvertEmotionElements = (keys: string[]) => (node: any) => {
- if (isPrimitive(node)) {
- return node
- }
- if (isEmotionCssPropEnzymeElement(node)) {
- const className = enzymeTickler.getTickledClassName(node.props.css)
- const labels = getLabelsFromClassName(keys, className || '')
-
- if (isShallowEnzymeElement(node, keys, labels)) {
- const emotionType = node.props.__EMOTION_TYPE_PLEASE_DO_NOT_USE__
- // emotionType will be a string for DOM elements
- const type =
- typeof emotionType === 'string'
- ? emotionType
- : emotionType.displayName || emotionType.name || 'Component'
+const createConvertEmotionElements =
+ (keys /*: string[]*/) => (node /*: any*/) => {
+ if (isPrimitive(node)) {
+ return node
+ }
+ if (isEmotionCssPropEnzymeElement(node)) {
+ const className = enzymeTickler.getTickledClassName(node.props.css)
+ const labels = getLabelsFromClassName(keys, className || '')
+
+ if (isShallowEnzymeElement(node, keys, labels)) {
+ const emotionType = node.props.__EMOTION_TYPE_PLEASE_DO_NOT_USE__
+ // emotionType will be a string for DOM elements
+ const type =
+ typeof emotionType === 'string'
+ ? emotionType
+ : emotionType.displayName || emotionType.name || 'Component'
+ return {
+ ...node,
+ props: filterEmotionProps({
+ ...node.props,
+ className
+ }),
+ type
+ }
+ } else {
+ return node.children[node.children.length - 1]
+ }
+ }
+ if (isEmotionCssPropElementType(node)) {
return {
...node,
- props: filterEmotionProps({
- ...node.props,
- className
- }),
- type
+ props: filterEmotionProps(node.props),
+ type: node.props.__EMOTION_TYPE_PLEASE_DO_NOT_USE__
}
- } else {
- return node.children[node.children.length - 1]
}
- }
- if (isEmotionCssPropElementType(node)) {
- return {
- ...node,
- props: filterEmotionProps(node.props),
- type: node.props.__EMOTION_TYPE_PLEASE_DO_NOT_USE__
+ if (isReactElement(node)) {
+ return copyProps({}, node)
}
+ return node
}
- if (isReactElement(node)) {
- return copyProps({}, node)
- }
- return node
-}
-function clean(node: any, classNames: string[]) {
+function clean(node, classNames /*: string[] */) {
if (Array.isArray(node)) {
for (const child of node) {
clean(child, classNames)
@@ -186,17 +188,17 @@ export function createSerializer({
classNameReplacer,
DOMElements = true,
includeStyles = true
-}: Options = {}) {
+} /* : Options */ = {}) {
const cache = new WeakSet()
const isTransformed = val => cache.has(val)
function serialize(
- val: *,
- config: *,
- indentation: string,
- depth: number,
- refs: *,
- printer: Function
+ val,
+ config,
+ indentation /*: string */,
+ depth /*: number */,
+ refs,
+ printer /*: Function */
) {
const elements = getStyleElements()
const keys = getKeys(elements)
@@ -223,7 +225,7 @@ export function createSerializer({
}
return {
- test(val: *) {
+ test(val) {
return (
val &&
!isTransformed(val) &&
diff --git a/packages/jest/src/enzyme-serializer.js b/packages/jest/src/enzyme-serializer.js
index 78c5bba6ce..2b73962978 100644
--- a/packages/jest/src/enzyme-serializer.js
+++ b/packages/jest/src/enzyme-serializer.js
@@ -1,3 +1,2 @@
-// @flow
import { createEnzymeSerializer } from './create-enzyme-serializer'
export const { test, serialize } = createEnzymeSerializer()
diff --git a/packages/jest/src/enzyme.js b/packages/jest/src/enzyme.js
index 929a5b359f..72fdee8bd1 100644
--- a/packages/jest/src/enzyme.js
+++ b/packages/jest/src/enzyme.js
@@ -1,3 +1,2 @@
-// @flow
export { createEnzymeSerializer } from './create-enzyme-serializer'
export { matchers } from './matchers'
diff --git a/packages/jest/src/index.js b/packages/jest/src/index.js
index 0b67c3dd0d..c675404fda 100644
--- a/packages/jest/src/index.js
+++ b/packages/jest/src/index.js
@@ -1,3 +1,2 @@
-// @flow
export { createSerializer } from './create-serializer'
export { matchers } from './matchers'
diff --git a/packages/jest/src/matchers.js b/packages/jest/src/matchers.js
index 5e648fcca5..4edae6bb6c 100644
--- a/packages/jest/src/matchers.js
+++ b/packages/jest/src/matchers.js
@@ -1,4 +1,3 @@
-// @flow
import chalk from 'chalk'
import * as stylis from 'stylis'
import * as specificity from 'specificity'
@@ -40,10 +39,10 @@ function valueMatches(declaration, value) {
}
function toHaveStyleRule(
- received: *,
- property: *,
- value: *,
- options?: { target?: string | RegExp, media?: string } = {}
+ received,
+ property,
+ value,
+ options /* ?: { target?: string | RegExp, media?: string } */ = {}
) {
if (Array.isArray(received)) {
throw new Error(
diff --git a/packages/jest/src/replace-class-names.js b/packages/jest/src/replace-class-names.js
index 892b67081b..713b7c8b26 100644
--- a/packages/jest/src/replace-class-names.js
+++ b/packages/jest/src/replace-class-names.js
@@ -1,4 +1,3 @@
-// @flow
function defaultClassNameReplacer(className, index) {
return `emotion-${index}`
}
@@ -6,14 +5,14 @@ function defaultClassNameReplacer(className, index) {
const componentSelectorClassNamePattern = /^e[a-zA-Z0-9]+[0-9]+$/
export const replaceClassNames = (
- classNames: Array,
- styles: string,
- code: string,
- keys: Array,
- classNameReplacer: (
+ classNames /*: Array */,
+ styles /*: string */,
+ code /*: string */,
+ keys /*: Array */,
+ classNameReplacer /*: (
className: string,
index: number
- ) => string = defaultClassNameReplacer
+ ) => string */ = defaultClassNameReplacer
) => {
let index = 0
let keyPattern = new RegExp(`^(${keys.join('|')})-`)
diff --git a/packages/jest/src/serializer.js b/packages/jest/src/serializer.js
index 3f6afed572..941aa43682 100644
--- a/packages/jest/src/serializer.js
+++ b/packages/jest/src/serializer.js
@@ -1,3 +1,2 @@
-// @flow
import { createSerializer } from './create-serializer'
export const { test, serialize } = createSerializer()
diff --git a/packages/jest/src/utils.js b/packages/jest/src/utils.js
index 8a4cad723b..378dec2dae 100644
--- a/packages/jest/src/utils.js
+++ b/packages/jest/src/utils.js
@@ -1,16 +1,20 @@
-// @flow
-
const isBrowser = typeof document !== 'undefined'
function last(arr) {
return arr.length > 0 ? arr[arr.length - 1] : undefined
}
-export function flatMap(arr: T[], iteratee: (arg: T) => S[] | S): S[] {
+export function flatMap /* */(
+ arr /*: T[] */,
+ iteratee /*: (arg: T) => S[] | S */
+) /*: S[] */ {
return [].concat(...arr.map(iteratee))
}
-export function findLast(arr: T[], predicate: T => boolean) {
+export function findLast /* */(
+ arr /*: T[] */,
+ predicate /*: T => boolean */
+) {
for (let i = arr.length - 1; i >= 0; i--) {
if (predicate(arr[i])) {
return arr[i]
@@ -18,10 +22,10 @@ export function findLast(arr: T[], predicate: T => boolean) {
}
}
-export function findIndexFrom(
- arr: T[],
- fromIndex: number,
- predicate: T => boolean
+export function findIndexFrom /* */(
+ arr /*: T[] */,
+ fromIndex /*: number */,
+ predicate /*: T => boolean */
) {
for (let i = fromIndex; i < arr.length; i++) {
if (predicate(arr[i])) {
@@ -32,7 +36,7 @@ export function findIndexFrom(
return -1
}
-function getClassNames(selectors: any, classes?: string) {
+function getClassNames(selectors, classes /* ?: string */) {
return classes ? selectors.concat(classes.split(' ')) : selectors
}
@@ -58,7 +62,7 @@ function getClassNameProp(node) {
return (node && node.prop('className')) || ''
}
-export function unwrapFromPotentialFragment(node: *) {
+export function unwrapFromPotentialFragment(node) {
if (node.type() === Symbol.for('react.fragment')) {
const isShallow = !!node.dive
if (isShallow) {
@@ -86,25 +90,25 @@ function getClassNamesFromCheerio(selectors, node) {
return getClassNames(selectors, classes)
}
-function getClassNamesFromDOMElement(selectors, node: any) {
+function getClassNamesFromDOMElement(selectors, node) {
return getClassNames(selectors, node.getAttribute('class'))
}
-export function isReactElement(val: any): boolean {
+export function isReactElement(val) /*: boolean */ {
return (
val.$$typeof === Symbol.for('react.test.json') ||
val.$$typeof === Symbol.for('react.element')
)
}
-export function isEmotionCssPropElementType(val: any): boolean {
+export function isEmotionCssPropElementType(val) /*: boolean */ {
return (
val.$$typeof === Symbol.for('react.element') &&
val.type.displayName === 'EmotionCssPropInternal'
)
}
-export function isStyledElementType(val: any): boolean {
+export function isStyledElementType(val /* : any */) /* : boolean */ {
if (val.$$typeof !== Symbol.for('react.element')) {
return false
}
@@ -112,7 +116,7 @@ export function isStyledElementType(val: any): boolean {
return type.__emotion_real === type
}
-export function isEmotionCssPropEnzymeElement(val: any): boolean {
+export function isEmotionCssPropEnzymeElement(val /* : any */) /*: boolean */ {
return (
val.$$typeof === Symbol.for('react.test.json') &&
val.type === 'EmotionCssPropInternal'
@@ -120,7 +124,7 @@ export function isEmotionCssPropEnzymeElement(val: any): boolean {
}
const domElementPattern = /^((HTML|SVG)\w*)?Element$/
-export function isDOMElement(val: any): boolean {
+export function isDOMElement(val) /*: boolean */ {
return (
val.nodeType === 1 &&
val.constructor &&
@@ -129,15 +133,15 @@ export function isDOMElement(val: any): boolean {
)
}
-function isEnzymeElement(val: any): boolean {
+function isEnzymeElement(val) /*: boolean */ {
return typeof val.findWhere === 'function'
}
-function isCheerioElement(val: any): boolean {
+function isCheerioElement(val) /*: boolean */ {
return val.cheerio === '[cheerio object]'
}
-export function getClassNamesFromNodes(nodes: Array) {
+export function getClassNamesFromNodes(nodes /*: Array */) {
return nodes.reduce((selectors, node) => {
if (isEnzymeElement(node)) {
return getClassNamesFromEnzyme(selectors, node)
@@ -154,7 +158,7 @@ const keyframesPattern = /^@keyframes\s+(animation-[^{\s]+)+/
const removeCommentPattern = /\/\*[\s\S]*?\*\//g
-const getElementRules = (element: HTMLStyleElement): string[] => {
+const getElementRules = (element /*: HTMLStyleElement */) /*: string[] */ => {
const nonSpeedyRule = element.textContent
if (nonSpeedyRule) {
return [nonSpeedyRule]
@@ -162,7 +166,6 @@ const getElementRules = (element: HTMLStyleElement): string[] => {
if (!element.sheet) {
return []
}
- // $FlowFixMe - flow doesn't know about `cssRules` property
return [].slice.call(element.sheet.cssRules).map(cssRule => cssRule.cssText)
}
@@ -180,9 +183,9 @@ const getKeyframesMap = rules =>
}, {})
export function getStylesFromClassNames(
- classNames: Array,
- elements: Array
-): string {
+ classNames /*: Array */,
+ elements /*: Array */
+) /*: string */ {
if (!classNames.length) {
return ''
}
@@ -212,7 +215,7 @@ export function getStylesFromClassNames(
const rules = flatMap(elements, getElementRules)
let styles = rules
- .map((rule: string) => {
+ .map((rule /*: string */) => {
const match = rule.match(selectorPattern)
if (!match) {
return null
@@ -259,35 +262,30 @@ export function getStylesFromClassNames(
return (keyframesStyles + styles).replace(removeCommentPattern, '')
}
-export function getStyleElements(): Array {
+export function getStyleElements() /*: Array */ {
if (!isBrowser) {
throw new Error(
'jest-emotion requires jsdom. See https://jestjs.io/docs/en/configuration#testenvironment-string for more information.'
)
}
const elements = Array.from(document.querySelectorAll('style[data-emotion]'))
- // $FlowFixMe
return elements
}
const unique = arr => Array.from(new Set(arr))
-export function getKeys(elements: Array) {
+export function getKeys(elements /*: Array */) {
const keys = unique(
- elements.map(
- element =>
- // $FlowFixMe we know it exists since we query for elements with this attribute
- (element.getAttribute('data-emotion'): string)
- )
+ elements.map(element => element.getAttribute('data-emotion'))
).filter(Boolean)
return keys
}
export function hasClassNames(
- classNames: Array,
- selectors: Array,
- target?: string | RegExp
-): boolean {
+ classNames /*: Array */,
+ selectors /*: Array */,
+ target /* ?: string | RegExp */
+) /*: boolean */ {
// selectors is the classNames of specific css rule
return selectors.some(selector => {
// if no target, use className of the specific css rule and try to find it
@@ -307,7 +305,10 @@ export function hasClassNames(
})
}
-export function getMediaRules(rules: Array, media: string): Array {
+export function getMediaRules(
+ rules /*: Array */,
+ media /*: string */
+) /*: Array */ {
return flatMap(
rules.filter(rule => {
if (rule.type !== '@media') {
@@ -319,10 +320,10 @@ export function getMediaRules(rules: Array, media: string): Array {
)
}
-export function isPrimitive(test: any) {
+export function isPrimitive(test) {
return test !== Object(test)
}
-export function hasIntersection(left: any[], right: any[]) {
+export function hasIntersection(left /* any[] */, right /* any[] */) {
return left.some(value => right.includes(value))
}
diff --git a/packages/jest/test/printer.test.js b/packages/jest/test/printer.test.js
index e7f0c0837a..3a90c7f8bd 100644
--- a/packages/jest/test/printer.test.js
+++ b/packages/jest/test/printer.test.js
@@ -1,4 +1,3 @@
-// @flow
import React from 'react'
import 'test-utils/legacy-env'
import renderer from 'react-test-renderer'
diff --git a/packages/memoize/package.json b/packages/memoize/package.json
index d017e54bf2..217ea21558 100644
--- a/packages/memoize/package.json
+++ b/packages/memoize/package.json
@@ -4,7 +4,7 @@
"description": "emotion's memoize utility",
"main": "dist/emotion-memoize.cjs.js",
"module": "dist/emotion-memoize.esm.js",
- "types": "types/index.d.ts",
+ "types": "dist/emotion-memoize.cjs.d.ts",
"license": "MIT",
"repository": "https://github.com/emotion-js/emotion/tree/main/packages/memoize",
"scripts": {
@@ -19,8 +19,7 @@
},
"files": [
"src",
- "dist",
- "types/*.d.ts"
+ "dist"
],
"exports": {
".": {
diff --git a/packages/memoize/src/index.d.ts b/packages/memoize/src/index.d.ts
deleted file mode 100644
index 9e46093759..0000000000
--- a/packages/memoize/src/index.d.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from '../types'
-export { default } from '../types'
diff --git a/packages/memoize/src/index.js b/packages/memoize/src/index.js
deleted file mode 100644
index b1e3741a18..0000000000
--- a/packages/memoize/src/index.js
+++ /dev/null
@@ -1,10 +0,0 @@
-// @flow
-
-export default function memoize(fn: string => V): string => V {
- const cache = Object.create(null)
-
- return (arg: string) => {
- if (cache[arg] === undefined) cache[arg] = fn(arg)
- return cache[arg]
- }
-}
diff --git a/packages/memoize/src/index.ts b/packages/memoize/src/index.ts
new file mode 100644
index 0000000000..2f218b1c8c
--- /dev/null
+++ b/packages/memoize/src/index.ts
@@ -0,0 +1,8 @@
+export default function memoize(fn: (arg: string) => V): (arg: string) => V {
+ const cache: Record = Object.create(null)
+
+ return (arg: string) => {
+ if (cache[arg] === undefined) cache[arg] = fn(arg)
+ return cache[arg]
+ }
+}
diff --git a/packages/memoize/types/index.d.ts b/packages/memoize/types/index.d.ts
index 23f3580f10..2c736dff8d 100644
--- a/packages/memoize/types/index.d.ts
+++ b/packages/memoize/types/index.d.ts
@@ -1,3 +1 @@
-type Fn = (key: string) => T
-
-export default function memoize(fn: Fn): Fn
+export { default } from '..'
diff --git a/packages/memoize/types/tslint.json b/packages/memoize/types/tslint.json
index 2ab14e84ff..20bc577159 100644
--- a/packages/memoize/types/tslint.json
+++ b/packages/memoize/types/tslint.json
@@ -18,6 +18,7 @@
],
"no-unnecessary-generics": false,
- "strict-export-declare-modifiers": false
+ "strict-export-declare-modifiers": false,
+ "no-default-import": false
}
}
diff --git a/packages/native/test/native-css.test.js b/packages/native/test/native-css.test.js
index ac63ae78fe..f3f0bf870d 100644
--- a/packages/native/test/native-css.test.js
+++ b/packages/native/test/native-css.test.js
@@ -31,7 +31,6 @@ describe('Emotion native css', () => {
// this test checks the keys instead of the objects
// because we care about the order of the keys
expect(
- // $FlowFixMe
Object.keys(
StyleSheet.flatten(
css({ color: 'green' }, `background-color:yellow;`, { flex: 2 })
@@ -39,7 +38,6 @@ describe('Emotion native css', () => {
)
).toEqual(['color', 'backgroundColor', 'flex'])
expect(
- // $FlowFixMe
Object.keys(
StyleSheet.flatten(
css([
@@ -52,7 +50,6 @@ describe('Emotion native css', () => {
)
).toEqual(['color', 'backgroundColor', 'flex'])
expect(
- // $FlowFixMe
Object.keys(
StyleSheet.flatten(
css([
@@ -68,7 +65,6 @@ describe('Emotion native css', () => {
)
).toEqual(['color', 'backgroundColor', 'flex'])
expect(
- // $FlowFixMe
Object.keys(
StyleSheet.flatten(
css([
diff --git a/packages/primitives-core/package.json b/packages/primitives-core/package.json
index 17e65a5622..87ff3459de 100644
--- a/packages/primitives-core/package.json
+++ b/packages/primitives-core/package.json
@@ -4,6 +4,7 @@
"description": "Shared utilities for emotion primitives and native",
"main": "dist/emotion-primitives-core.cjs.js",
"module": "dist/emotion-primitives-core.esm.js",
+ "types": "dist/emotion-primitives-core.cjs.d.ts",
"files": [
"src",
"dist"
@@ -18,6 +19,7 @@
},
"devDependencies": {
"@emotion/react": "11.11.4",
+ "@types/css-to-react-native": "^3.0.0",
"react": "16.14.0"
},
"homepage": "https://emotion.sh",
diff --git a/packages/primitives-core/src/css.js b/packages/primitives-core/src/css.ts
similarity index 77%
rename from packages/primitives-core/src/css.js
rename to packages/primitives-core/src/css.ts
index 3d993c80f1..fde7c11674 100644
--- a/packages/primitives-core/src/css.js
+++ b/packages/primitives-core/src/css.ts
@@ -1,17 +1,22 @@
-// @flow
-import transform from 'css-to-react-native'
+import transform, { Style } from 'css-to-react-native'
+import { AbstractStyleSheet } from './types'
import { interleave } from './utils'
// this is for handleInterpolation
// they're reset on every call to css
// this is done so we don't create a new
// handleInterpolation function on every css call
-let styles
-let generated = {}
+let styles: unknown[] | undefined
+let generated: Record = {}
let buffer = ''
-let lastType
-
-function handleInterpolation(interpolation: *, i: number, arr: Array<*>) {
+let lastType: string | undefined
+
+function handleInterpolation(
+ this: unknown,
+ interpolation: any,
+ i: number,
+ arr: any[]
+) {
let type = typeof interpolation
if (type === 'string') {
@@ -31,15 +36,7 @@ function handleInterpolation(interpolation: *, i: number, arr: Array<*>) {
)
}
} else {
- handleInterpolation.call(
- this,
- interpolation(
- // $FlowFixMe
- this
- ),
- i,
- arr
- )
+ handleInterpolation.call(this, interpolation(this), i, arr)
}
return
}
@@ -49,7 +46,7 @@ function handleInterpolation(interpolation: *, i: number, arr: Array<*>) {
if (lastType === 'string' && (isRnStyle || isIrrelevant)) {
let converted = convertStyles(buffer)
if (converted !== undefined) {
- styles.push(converted)
+ styles!.push(converted)
}
buffer = ''
}
@@ -63,13 +60,13 @@ function handleInterpolation(interpolation: *, i: number, arr: Array<*>) {
if (arr.length - 1 === i) {
let converted = convertStyles(buffer)
if (converted !== undefined) {
- styles.push(converted)
+ styles!.push(converted)
}
buffer = ''
}
}
if (isRnStyle) {
- styles.push(interpolation)
+ styles!.push(interpolation)
}
if (Array.isArray(interpolation)) {
interpolation.forEach(handleInterpolation, this)
@@ -79,10 +76,10 @@ function handleInterpolation(interpolation: *, i: number, arr: Array<*>) {
// Use platform specific StyleSheet method for creating the styles.
// This enables us to use the css``/css({}) in any environment (Native | Sketch | Web)
-export function createCss(StyleSheet: Object) {
- return function css(...args: any) {
+export function createCss(StyleSheet: AbstractStyleSheet) {
+ return function css(this: unknown, ...args: any[]) {
const prevBuffer = buffer
- let vals
+ let vals: any[]
// these are declared earlier
// this is done so we don't create a new
@@ -94,7 +91,7 @@ export function createCss(StyleSheet: Object) {
if (args[0] == null || args[0].raw === undefined) {
vals = args
} else {
- vals = interleave(args)
+ vals = interleave(args as [any, ...any[]])
}
try {
@@ -116,7 +113,7 @@ export function createCss(StyleSheet: Object) {
let propertyValuePattern = /\s*([^\s]+)\s*:\s*(.+?)\s*$/
-function convertPropertyValue(style) {
+function convertPropertyValue(this: [string, string][], style: string): void {
// Get prop name and prop value
let match = propertyValuePattern.exec(style)
// match[2] will be " " in cases where there is no value
@@ -126,14 +123,14 @@ function convertPropertyValue(style) {
// be the whole string so we remove it
match.shift()
// yes i know this looks funny
- this.push(match)
+ this.push(match as unknown as [string, string])
}
}
-function convertStyles(str: string) {
+function convertStyles(str: string): Style | undefined {
if (str.trim() === '') return
- const stylePairs = []
+ const stylePairs: [string, string][] = []
const parsedString = str.split(';')
@@ -142,9 +139,9 @@ function convertStyles(str: string) {
try {
return transform(stylePairs)
} catch (error) {
- const msg = error.message
+ const msg = (error as { message?: string } | undefined)?.message
- if (msg.includes('Failed to parse declaration')) {
+ if (msg && msg.includes('Failed to parse declaration')) {
const values = msg
.replace('Failed to parse declaration ', '')
.replace(/"/g, '')
diff --git a/packages/primitives-core/src/index.js b/packages/primitives-core/src/index.ts
similarity index 100%
rename from packages/primitives-core/src/index.js
rename to packages/primitives-core/src/index.ts
diff --git a/packages/primitives-core/src/styled.js b/packages/primitives-core/src/styled.ts
similarity index 62%
rename from packages/primitives-core/src/styled.js
rename to packages/primitives-core/src/styled.ts
index f5771552e8..e9371e3490 100644
--- a/packages/primitives-core/src/styled.js
+++ b/packages/primitives-core/src/styled.ts
@@ -1,25 +1,31 @@
-// @flow
import * as React from 'react'
import { interleave } from './utils'
import { ThemeContext } from '@emotion/react'
import { createCss } from './css'
+import { AbstractStyleSheet } from './types'
-let testOmitPropsOnComponent = prop => prop !== 'theme' && prop !== 'as'
+let testOmitPropsOnComponent = (prop: string) =>
+ prop !== 'theme' && prop !== 'as'
-type CreateStyledOptions = {
- getShouldForwardProp: (cmp: React.ElementType) => (prop: string) => boolean
+interface CreateStyledOptions {
+ getShouldForwardProp(cmp: React.ElementType): (prop: string) => boolean
}
-type StyledOptions = {
- shouldForwardProp?: (prop: string) => boolean
+interface StyledOptions {
+ shouldForwardProp?(prop: string): boolean
+}
+
+type StyledProps = Record & {
+ as?: React.ElementType
}
export function createStyled(
- StyleSheet: Object,
- {
- getShouldForwardProp = () => testOmitPropsOnComponent
- }: CreateStyledOptions = {}
+ StyleSheet: AbstractStyleSheet,
+ options?: CreateStyledOptions
) {
+ const getShouldForwardProp =
+ options?.getShouldForwardProp ?? (() => testOmitPropsOnComponent)
+
const css = createCss(StyleSheet)
return function createEmotion(
@@ -34,18 +40,17 @@ export function createStyled(
shouldForwardProp || getShouldForwardProp(component)
let shouldUseAs = !defaultShouldForwardProp('as')
- return function createStyledComponent(...rawStyles: *) {
- let styles
+ return function createStyledComponent(...rawStyles: any[]) {
+ let styles: any[]
if (rawStyles[0] == null || rawStyles[0].raw === undefined) {
styles = rawStyles
} else {
- styles = interleave(rawStyles)
+ styles = interleave(rawStyles as [any, ...any[]])
}
// do we really want to use the same infra as the web since it only really uses theming?
- // $FlowFixMe
- let Styled = React.forwardRef((props, ref) => {
+ let Styled = React.forwardRef((props, ref) => {
const finalTag = (shouldUseAs && props.as) || component
let mergedProps = props
@@ -62,7 +67,7 @@ export function createStyled(
? getShouldForwardProp(finalTag)
: defaultShouldForwardProp
- let newProps = {}
+ let newProps: Record = {}
for (let key in props) {
if (shouldUseAs && key === 'as') continue
@@ -75,21 +80,28 @@ export function createStyled(
newProps.style = [css.apply(mergedProps, styles), props.style]
newProps.ref = ref
- // $FlowFixMe
return React.createElement(finalTag, newProps)
})
- // $FlowFixMe
- Styled.withComponent = (newComponent: React.ElementType) =>
- createEmotion(newComponent)(...styles)
Styled.displayName = `emotion(${getDisplayName(component)})`
- return Styled
+ const withComponent = (newComponent: React.ElementType) =>
+ createEmotion(newComponent)(...styles)
+
+ const castedStyled = Styled as typeof Styled & {
+ withComponent: typeof withComponent
+ }
+
+ castedStyled.withComponent = withComponent
+
+ return castedStyled
}
}
}
-const getDisplayName = primitive =>
+const getDisplayName = (
+ primitive: string | { displayName?: string; name?: string }
+) =>
typeof primitive === 'string'
? primitive
: primitive.displayName || primitive.name || 'Styled'
diff --git a/packages/primitives-core/src/types.ts b/packages/primitives-core/src/types.ts
new file mode 100644
index 0000000000..f606163c52
--- /dev/null
+++ b/packages/primitives-core/src/types.ts
@@ -0,0 +1,10 @@
+type NamedStyles = { [P in keyof T]: unknown }
+
+// This is based on the StyleSheet type from @types/react-native
+export interface AbstractStyleSheet {
+ create | NamedStyles>(
+ styles: T | NamedStyles
+ ): T
+
+ flatten(style?: unknown[]): unknown
+}
diff --git a/packages/primitives-core/src/utils.js b/packages/primitives-core/src/utils.ts
similarity index 61%
rename from packages/primitives-core/src/utils.js
rename to packages/primitives-core/src/utils.ts
index 953c2043dc..49ee502438 100644
--- a/packages/primitives-core/src/utils.js
+++ b/packages/primitives-core/src/utils.ts
@@ -1,8 +1,8 @@
-// @flow
-
-export function interleave(vals: Array<*>) {
+export function interleave(
+ vals: [TemplateStringsArray, ...unknown[]]
+): unknown[] {
let strings = vals[0]
- let finalArray = [strings[0]]
+ let finalArray: unknown[] = [strings[0]]
for (let i = 1, len = vals.length; i < len; i++) {
finalArray.push(vals[i])
if (strings[i] !== undefined) {
diff --git a/packages/primitives/src/index.js b/packages/primitives/src/index.js
index 0dcb3a0d03..a7155513cc 100644
--- a/packages/primitives/src/index.js
+++ b/packages/primitives/src/index.js
@@ -1,4 +1,3 @@
-// @flow
import { StyleSheet, Text, View, Image } from 'react-primitives'
import { createCss } from '@emotion/primitives-core'
diff --git a/packages/primitives/src/styled.js b/packages/primitives/src/styled.js
index 894812d670..6e67d9b9f9 100644
--- a/packages/primitives/src/styled.js
+++ b/packages/primitives/src/styled.js
@@ -1,4 +1,3 @@
-// @flow
import * as React from 'react'
import { StyleSheet, View, Text, Image } from 'react-primitives'
import { createStyled } from '@emotion/primitives-core'
@@ -7,7 +6,7 @@ import {
testPickPropsOnOtherComponent
} from './test-props'
-function getShouldForwardProp(component: React.ElementType) {
+function getShouldForwardProp(component /*: React.ElementType */) {
switch (component) {
case View:
case Text:
@@ -22,6 +21,7 @@ function getShouldForwardProp(component: React.ElementType) {
* a function that returns a styled component which render styles on multiple targets with same code
*/
+/*
type CreateStyledComponent = (
...styles: any
) => React.StatelessFunctionalComponent & {
@@ -35,7 +35,8 @@ export type Styled = BaseStyled & {
Text: CreateStyledComponent,
Image: CreateStyledComponent
}
+*/
-let styled: Styled = createStyled(StyleSheet, { getShouldForwardProp })
+let styled /*: Styled */ = createStyled(StyleSheet, { getShouldForwardProp })
export { styled }
diff --git a/packages/primitives/src/test-props.js b/packages/primitives/src/test-props.js
index aa19f7f78f..ad72f3037a 100644
--- a/packages/primitives/src/test-props.js
+++ b/packages/primitives/src/test-props.js
@@ -1,4 +1,3 @@
-// @flow
import isPropValid from '@emotion/is-prop-valid'
const forwardableProps = {
@@ -49,7 +48,7 @@ const forwardableProps = {
textBreakStrategy: true
}
-export function testPickPropsOnPrimitiveComponent(prop: string) {
+export function testPickPropsOnPrimitiveComponent(prop /*: string */) {
return (
forwardableProps[prop] === true ||
// This will allow the standard react props
@@ -59,6 +58,6 @@ export function testPickPropsOnPrimitiveComponent(prop: string) {
)
}
-export function testPickPropsOnOtherComponent(prop: string) {
+export function testPickPropsOnOtherComponent(prop /*: string */) {
return prop !== 'theme'
}
diff --git a/packages/primitives/test/css.test.js b/packages/primitives/test/css.test.js
index 93fc9b2199..a5b0882d39 100644
--- a/packages/primitives/test/css.test.js
+++ b/packages/primitives/test/css.test.js
@@ -1,4 +1,3 @@
-// @flow
import { css } from '@emotion/primitives'
import { StyleSheet } from 'react-native'
@@ -29,7 +28,6 @@ test('order with string and object', () => {
// this test checks the keys instead of the objects
// because we care about the order of the keys
expect(
- // $FlowFixMe
Object.keys(
StyleSheet.flatten(
css({ color: 'green' }, `background-color:yellow;`, { flex: 2 })
@@ -37,7 +35,6 @@ test('order with string and object', () => {
)
).toEqual(['color', 'backgroundColor', 'flex'])
expect(
- // $FlowFixMe
Object.keys(
StyleSheet.flatten(
css([
@@ -50,7 +47,6 @@ test('order with string and object', () => {
)
).toEqual(['color', 'backgroundColor', 'flex'])
expect(
- // $FlowFixMe
Object.keys(
StyleSheet.flatten(
css([
@@ -66,7 +62,6 @@ test('order with string and object', () => {
)
).toEqual(['color', 'backgroundColor', 'flex'])
expect(
- // $FlowFixMe
Object.keys(
StyleSheet.flatten(
css([
diff --git a/packages/primitives/test/emotion-primitives.test.js b/packages/primitives/test/emotion-primitives.test.js
index 035b08c128..dc2c1bbaa3 100644
--- a/packages/primitives/test/emotion-primitives.test.js
+++ b/packages/primitives/test/emotion-primitives.test.js
@@ -1,4 +1,3 @@
-// @flow
import * as React from 'react'
import renderer from 'react-test-renderer'
import { Text, StyleSheet } from 'react-primitives'
@@ -17,7 +16,6 @@ describe('Emotion primitives', () => {
})
test('should throw an error when used invalid primitive', () => {
- // $FlowFixMe: expect error
expect(() => styled.TEXT({})).toThrow()
})
@@ -29,7 +27,6 @@ describe('Emotion primitives', () => {
`
const tree = renderer
.create(
- // $FlowFixMe
Emotion Primitives
@@ -46,7 +43,6 @@ describe('Emotion primitives', () => {
const tree = renderer
.create(
- {/* $FlowFixMe */}
Hello World
)
@@ -62,7 +58,6 @@ describe('Emotion primitives', () => {
const { container, unmount } = render(
- {/* $FlowFixMe */}
Hello World
@@ -78,7 +73,6 @@ describe('Emotion primitives', () => {
color: props.decor
}))
const tree = renderer
- // $FlowFixMe
.create(Emotion Primitives )
.toJSON()
expect(tree).toMatchSnapshot()
@@ -89,10 +83,7 @@ describe('Emotion primitives', () => {
color: hotpink;
`
const tree = renderer
- .create(
- // $FlowFixMe
- Emotion primitives
- )
+ .create(Emotion primitives )
.toJSON()
expect(tree).toMatchSnapshot()
})
@@ -104,7 +95,6 @@ describe('Emotion primitives', () => {
`
const tree = renderer
- // $FlowFixMe
.create(Emotion Primitives )
.toJSON()
expect(tree).toMatchSnapshot()
@@ -114,7 +104,6 @@ describe('Emotion primitives', () => {
const StyledText = styled.Text`
color: ${props => props.decor};
`
- // $FlowFixMe
const Name = StyledText.withComponent(Text)
const tree = renderer.create(Mike ).toJSON()
expect(tree).toMatchSnapshot()
@@ -124,13 +113,11 @@ describe('Emotion primitives', () => {
const Text = styled.Text`
color: hotpink;
`
- // $FlowFixMe
const Title = () => Hello World
const StyledTitle = styled(Title)`
font-size: 20px;
font-style: ${props => props.sty};
`
- // $FlowFixMe
const tree = renderer.create( ).toJSON()
expect(tree).toMatchSnapshot()
})
@@ -151,9 +138,7 @@ describe('Emotion primitives', () => {
const ViewOne = styled.View`
background-color: ${props => props.color};
`
- // $FlowFixMe
const treeOne = renderer.create( )
- // $FlowFixMe
const ViewTwo = ViewOne.withComponent(Text)
const treeTwo = renderer.create( )
@@ -167,7 +152,6 @@ describe('Emotion primitives', () => {
`
const tree = renderer
.create(
- // $FlowFixMe
{
test('custom shouldForwardProp works', () => {
const Text = styled.Text``
const Title = props =>
- // $FlowFixMe
const StyledTitle = styled(Title, {
shouldForwardProp: prop => prop !== 'color' && prop !== 'theme'
})`
diff --git a/packages/primitives/test/no-babel/basic.test.js b/packages/primitives/test/no-babel/basic.test.js
index be39d3ab15..7697ac1256 100644
--- a/packages/primitives/test/no-babel/basic.test.js
+++ b/packages/primitives/test/no-babel/basic.test.js
@@ -1,4 +1,3 @@
-// @flow
import * as React from 'react'
import styled, { css } from '@emotion/primitives'
import renderer from 'react-test-renderer'
@@ -48,7 +47,6 @@ test('should render the primitive when styles applied using object style notatio
`
const tree = renderer
.create(
- // $FlowFixMe
Emotion Primitives
diff --git a/packages/primitives/test/warnings.test.js b/packages/primitives/test/warnings.test.js
index 7aa51c2bb2..12e5ef993c 100644
--- a/packages/primitives/test/warnings.test.js
+++ b/packages/primitives/test/warnings.test.js
@@ -1,7 +1,5 @@
-// @flow
import { css } from '@emotion/primitives'
-// $FlowFixMe
console.error = jest.fn()
afterEach(() => {
diff --git a/packages/react/__tests__/at-import.js b/packages/react/__tests__/at-import.js
index 82f8e26445..f51250df63 100644
--- a/packages/react/__tests__/at-import.js
+++ b/packages/react/__tests__/at-import.js
@@ -1,4 +1,3 @@
-// @flow
import 'test-utils/prod-mode'
import * as React from 'react'
/** @jsx jsx */
@@ -7,9 +6,7 @@ import { render, unmountComponentAtNode } from 'react-dom'
import { Global, css } from '@emotion/react'
beforeEach(() => {
- // $FlowFixMe
document.head.innerHTML = ''
- // $FlowFixMe
document.body.innerHTML = `
`
})
@@ -26,7 +23,7 @@ test('basic', () => {
}
`}
/>
- , // $FlowFixMe
+ ,
document.getElementById('root')
)
expect(document.head).toMatchSnapshot()
@@ -34,7 +31,6 @@ test('basic', () => {
let elements = document.querySelectorAll('style')
let rules = []
for (let element of elements) {
- // $FlowFixMe
for (let cssRule of element.sheet.cssRules) {
rules.push(cssRule.cssText)
}
diff --git a/packages/react/__tests__/babel/__snapshots__/source-map-server.js.snap b/packages/react/__tests__/babel/__snapshots__/source-map-server.js.snap
index 66744f44d2..e7150e2a0f 100644
--- a/packages/react/__tests__/babel/__snapshots__/source-map-server.js.snap
+++ b/packages/react/__tests__/babel/__snapshots__/source-map-server.js.snap
@@ -1,3 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`basic 1`] = `"some hotpink text
"`;
+exports[`basic 1`] = `"some hotpink text
"`;
diff --git a/packages/react/__tests__/babel/source-map-server.js b/packages/react/__tests__/babel/source-map-server.js
index 60ecf18571..e55735edfb 100644
--- a/packages/react/__tests__/babel/source-map-server.js
+++ b/packages/react/__tests__/babel/source-map-server.js
@@ -1,7 +1,7 @@
/** @jsx jsx
* @jest-environment node
*/
-// @flow
+
import 'test-utils/dev-mode'
import { jsx } from '@emotion/react'
import { renderToString } from 'react-dom/server'
diff --git a/packages/react/__tests__/class-names.js b/packages/react/__tests__/class-names.js
index d165f3b593..7fe0c23050 100644
--- a/packages/react/__tests__/class-names.js
+++ b/packages/react/__tests__/class-names.js
@@ -1,4 +1,3 @@
-// @flow
import * as React from 'react'
import 'test-utils/next-env'
import { ClassNames, ThemeProvider } from '@emotion/react'
diff --git a/packages/react/__tests__/clone-element.js b/packages/react/__tests__/clone-element.js
index dedd52c62b..8a73c23938 100644
--- a/packages/react/__tests__/clone-element.js
+++ b/packages/react/__tests__/clone-element.js
@@ -1,4 +1,3 @@
-// @flow
/** @jsx jsx */
import { jsx } from '@emotion/react'
import * as React from 'react'
diff --git a/packages/react/__tests__/compat/browser.js b/packages/react/__tests__/compat/browser.js
index 450a1d2677..cd12840f2a 100644
--- a/packages/react/__tests__/compat/browser.js
+++ b/packages/react/__tests__/compat/browser.js
@@ -1,4 +1,3 @@
-// @flow
/** @jsx jsx */
import 'test-utils/dev-mode'
import { throwIfFalsy } from 'test-utils'
diff --git a/packages/react/__tests__/compat/server.js b/packages/react/__tests__/compat/server.js
index 08218a2513..4e72d857c1 100644
--- a/packages/react/__tests__/compat/server.js
+++ b/packages/react/__tests__/compat/server.js
@@ -1,6 +1,5 @@
/** @jsx jsx
* @jest-environment node
- * @flow
*/
import { jsx, Global } from '@emotion/react'
import createEmotionServer from '@emotion/server/create-instance'
diff --git a/packages/react/__tests__/css-cache-hash.js b/packages/react/__tests__/css-cache-hash.js
index 5e1a4fd55a..f7428bf46c 100644
--- a/packages/react/__tests__/css-cache-hash.js
+++ b/packages/react/__tests__/css-cache-hash.js
@@ -1,4 +1,3 @@
-// @flow
/** @jsx jsx */
import 'test-utils/next-env'
import { jsx, css } from '@emotion/react'
diff --git a/packages/react/__tests__/css.js b/packages/react/__tests__/css.js
index 9631e612e8..2d599f4df0 100644
--- a/packages/react/__tests__/css.js
+++ b/packages/react/__tests__/css.js
@@ -1,4 +1,3 @@
-// @flow
/** @jsx jsx */
import 'test-utils/next-env'
import { safeQuerySelector } from 'test-utils'
@@ -8,9 +7,7 @@ import { render } from '@testing-library/react'
import renderer from 'react-test-renderer'
import createCache from '@emotion/cache'
-// $FlowFixMe
console.error = jest.fn()
-// $FlowFixMe
console.warn = jest.fn()
afterEach(() => {
@@ -18,12 +15,11 @@ afterEach(() => {
safeQuerySelector('body').innerHTML = ''
})
-const SomeComponent = (props: { lol: true }) => (props.lol ? 'yes' : 'no')
+const SomeComponent = (props /*: { lol: true } */) => (props.lol ? 'yes' : 'no')
// test to make sure flow prop errors work.
// should probably try to make it so that components that require className props
// and have the css prop passed to them don't have type errors
-// $FlowFixMe
; // eslint-disable-line no-unused-expressions
test('thing', () => {
@@ -223,7 +219,7 @@ test('autoLabel without babel (sanitized)', () => {
})
test('overwrite styles from parent', () => {
- let SomeComponent = (props: Object) => (
+ let SomeComponent = (props /*: Object */) => (
{
})
test('applies class when css prop is set to nil on wrapper component', () => {
- const Button = (props: any) => (
-
- )
+ const Button = props =>
- const WrappedButton: React.StatelessFunctionalComponent
= ({
- children,
- buttonStyles
- }: {
+ const WrappedButton /*: React.StatelessFunctionalComponent */ = (
+ { children, buttonStyles } /*: {
children: React$Node,
buttonStyles?: null
- }) => {children}
+ } */
+ ) => {children}
const tree = renderer.create(
@@ -341,6 +334,6 @@ it("doesn't try to insert invalid rules caused by object style's value being fal
)
- expect((console.error: any).mock.calls).toMatchInlineSnapshot(`[]`)
- expect((console.warn: any).mock.calls).toMatchInlineSnapshot(`[]`)
+ expect(console.error.mock.calls).toMatchInlineSnapshot(`[]`)
+ expect(console.warn.mock.calls).toMatchInlineSnapshot(`[]`)
})
diff --git a/packages/react/__tests__/custom-cache.js b/packages/react/__tests__/custom-cache.js
index 2ccf1e3364..43907de7a4 100644
--- a/packages/react/__tests__/custom-cache.js
+++ b/packages/react/__tests__/custom-cache.js
@@ -1,4 +1,3 @@
-// @flow
/** @jsx jsx */
import createCache from '@emotion/cache'
import { CacheProvider, Global, jsx } from '@emotion/react'
diff --git a/packages/react/__tests__/global-with-theme.js b/packages/react/__tests__/global-with-theme.js
index 32b0d46c72..daa1f512b2 100644
--- a/packages/react/__tests__/global-with-theme.js
+++ b/packages/react/__tests__/global-with-theme.js
@@ -1,11 +1,9 @@
-// @flow
import 'test-utils/dev-mode'
import * as React from 'react'
import { render } from '@testing-library/react'
import { Global, ThemeProvider } from '@emotion/react'
beforeEach(() => {
- // $FlowFixMe
document.head.innerHTML = ''
})
diff --git a/packages/react/__tests__/global.js b/packages/react/__tests__/global.js
index 2ecc075407..06dc4c79f9 100644
--- a/packages/react/__tests__/global.js
+++ b/packages/react/__tests__/global.js
@@ -1,4 +1,3 @@
-// @flow
import 'test-utils/dev-mode'
import * as React from 'react'
import { render } from '@testing-library/react'
@@ -15,7 +14,6 @@ import createCache from '@emotion/cache'
console.error = jest.fn()
beforeEach(() => {
- // $FlowFixMe
document.head.innerHTML = ''
jest.resetAllMocks()
})
@@ -76,7 +74,6 @@ test('no React hook order violations', () => {
const theme = { color: 'blue' }
const cache = createCache({ key: 'context' })
- // $FlowFixMe
const Comp = ({ flag }) => (
diff --git a/packages/react/__tests__/globals-are-the-worst.js b/packages/react/__tests__/globals-are-the-worst.js
index 33d7dd1bd3..437dcaf9c1 100644
--- a/packages/react/__tests__/globals-are-the-worst.js
+++ b/packages/react/__tests__/globals-are-the-worst.js
@@ -1,4 +1,3 @@
-// @flow
import 'test-utils/dev-mode'
import { render } from '@testing-library/react'
import * as React from 'react'
diff --git a/packages/react/__tests__/import-prod.js b/packages/react/__tests__/import-prod.js
index a6ca906518..e357c881c5 100644
--- a/packages/react/__tests__/import-prod.js
+++ b/packages/react/__tests__/import-prod.js
@@ -1,4 +1,3 @@
-// @flow
import 'test-utils/prod-mode'
import * as React from 'react'
import * as ReactDOM from 'react-dom'
@@ -28,8 +27,8 @@ const render = children =>
// $FlowFixMe
document.body.appendChild(el)
- if ((ReactDOM: any).createRoot) {
- const root = (ReactDOM: any).createRoot(el)
+ if (ReactDOM.createRoot) {
+ const root = ReactDOM.createRoot(el)
root.render({children}
)
} else {
ReactDOM.render(children, el, resolve)
diff --git a/packages/react/__tests__/keyframes.js b/packages/react/__tests__/keyframes.js
index acf849f7da..481f866e08 100644
--- a/packages/react/__tests__/keyframes.js
+++ b/packages/react/__tests__/keyframes.js
@@ -1,4 +1,3 @@
-// @flow
/** @jsx jsx */
import 'test-utils/next-env'
import { jsx, css, keyframes } from '@emotion/react'
diff --git a/packages/react/__tests__/legacy-class-name.js b/packages/react/__tests__/legacy-class-name.js
index dd1d13dbf3..82345c4203 100644
--- a/packages/react/__tests__/legacy-class-name.js
+++ b/packages/react/__tests__/legacy-class-name.js
@@ -1,4 +1,3 @@
-// @flow
/** @jsx jsx */
import 'test-utils/next-env'
import { jsx, css } from '@emotion/react'
diff --git a/packages/react/__tests__/ref.js b/packages/react/__tests__/ref.js
index bb9766602f..0b82cce60b 100644
--- a/packages/react/__tests__/ref.js
+++ b/packages/react/__tests__/ref.js
@@ -1,4 +1,3 @@
-// @flow
/** @jsx jsx */
import { jsx } from '@emotion/react'
import * as React from 'react'
diff --git a/packages/react/__tests__/rehydration.js b/packages/react/__tests__/rehydration.js
index f03c88846a..113a96e2c2 100644
--- a/packages/react/__tests__/rehydration.js
+++ b/packages/react/__tests__/rehydration.js
@@ -1,10 +1,7 @@
-// @flow
/** @jsx jsx */
import { safeQuerySelector, disableBrowserEnvTemporarily } from 'test-utils'
-// $FlowFixMe
console.error = jest.fn()
-// $FlowFixMe
console.warn = jest.fn()
afterEach(() => {
@@ -87,8 +84,8 @@ test("cache created in render doesn't cause a hydration mismatch", () => {
container: safeQuerySelector('#root')
})
- expect((console.error: any).mock.calls).toMatchInlineSnapshot(`[]`)
- expect((console.warn: any).mock.calls).toMatchInlineSnapshot(`[]`)
+ expect(console.error.mock.calls).toMatchInlineSnapshot(`[]`)
+ expect(console.warn.mock.calls).toMatchInlineSnapshot(`[]`)
})
test('initializing another Emotion instance should not move already moved styles elements', () => {
@@ -607,13 +604,13 @@ test('duplicated global styles can be removed safely after rehydrating HTML SSRe
`)
})
-;((React: any).useId ? describe : describe.skip)('useId', () => {
+;(React.useId ? describe : describe.skip)('useId', () => {
test('no hydration mismatch for styled when using useId', async () => {
const finalHTML = await disableBrowserEnvTemporarily(() => {
resetAllModules()
const StyledDivWithId = styled(function DivWithId({ className }) {
- const id = (React: any).useId()
+ const id = React.useId()
return
})({
border: '1px solid black'
@@ -627,7 +624,7 @@ test('duplicated global styles can be removed safely after rehydrating HTML SSRe
resetAllModules()
const StyledDivWithId = styled(function DivWithId({ className }) {
- const id = (React: any).useId()
+ const id = React.useId()
return
})({
border: '1px solid black'
@@ -638,16 +635,16 @@ test('duplicated global styles can be removed safely after rehydrating HTML SSRe
container: safeQuerySelector('#root')
})
- expect((console.error: any).mock.calls).toMatchInlineSnapshot(`[]`)
- expect((console.warn: any).mock.calls).toMatchInlineSnapshot(`[]`)
+ expect(console.error.mock.calls).toMatchInlineSnapshot(`[]`)
+ expect(console.warn.mock.calls).toMatchInlineSnapshot(`[]`)
})
test('no hydration mismatch for css prop when using useId', async () => {
const finalHTML = await disableBrowserEnvTemporarily(() => {
resetAllModules()
- function DivWithId({ className }: { className?: string }) {
- const id = (React: any).useId()
+ function DivWithId({ className } /*: { className?: string }*/) {
+ const id = React.useId()
return
}
@@ -664,8 +661,8 @@ test('duplicated global styles can be removed safely after rehydrating HTML SSRe
resetAllModules()
- function DivWithId({ className }: { className?: string }) {
- const id = (React: any).useId()
+ function DivWithId({ className } /*: { className?: string }*/) {
+ const id = React.useId()
return
}
@@ -681,8 +678,8 @@ test('duplicated global styles can be removed safely after rehydrating HTML SSRe
}
)
- expect((console.error: any).mock.calls).toMatchInlineSnapshot(`[]`)
- expect((console.warn: any).mock.calls).toMatchInlineSnapshot(`[]`)
+ expect(console.error.mock.calls).toMatchInlineSnapshot(`[]`)
+ expect(console.warn.mock.calls).toMatchInlineSnapshot(`[]`)
})
test('no hydration mismatch for ClassNames when using useId', async () => {
@@ -690,7 +687,7 @@ test('duplicated global styles can be removed safely after rehydrating HTML SSRe
resetAllModules()
const DivWithId = ({ className }) => {
- const id = (React: any).useId()
+ const id = React.useId()
return
}
@@ -714,7 +711,7 @@ test('duplicated global styles can be removed safely after rehydrating HTML SSRe
resetAllModules()
const DivWithId = ({ className }) => {
- const id = (React: any).useId()
+ const id = React.useId()
return
}
@@ -736,7 +733,7 @@ test('duplicated global styles can be removed safely after rehydrating HTML SSRe
}
)
- expect((console.error: any).mock.calls).toMatchInlineSnapshot(`[]`)
- expect((console.warn: any).mock.calls).toMatchInlineSnapshot(`[]`)
+ expect(console.error.mock.calls).toMatchInlineSnapshot(`[]`)
+ expect(console.warn.mock.calls).toMatchInlineSnapshot(`[]`)
})
})
diff --git a/packages/react/__tests__/server.js b/packages/react/__tests__/server.js
index c6625a3851..44197477ff 100644
--- a/packages/react/__tests__/server.js
+++ b/packages/react/__tests__/server.js
@@ -1,7 +1,7 @@
/** @jsx jsx
* @jest-environment node
*/
-// @flow
+
import 'test-utils/dev-mode'
import * as React from 'react'
import testCases from 'jest-in-case'
diff --git a/packages/react/__tests__/theme-provider.dom.js b/packages/react/__tests__/theme-provider.dom.js
index 412539c751..4e56567773 100644
--- a/packages/react/__tests__/theme-provider.dom.js
+++ b/packages/react/__tests__/theme-provider.dom.js
@@ -1,4 +1,3 @@
-// @flow
/** @jsx jsx */
import 'test-utils/next-env'
import 'test-utils/dev-mode'
@@ -13,7 +12,7 @@ beforeEach(() => {
})
test('provider with theme value that changes', () => {
- class ThemeTest extends React.Component<*, *> {
+ class ThemeTest extends React.Component {
state = { theme: { color: 'hotpink', padding: 4 } }
render() {
return (
diff --git a/packages/react/__tests__/theme-provider.js b/packages/react/__tests__/theme-provider.js
index d9a06c0790..1e6b84bc64 100644
--- a/packages/react/__tests__/theme-provider.js
+++ b/packages/react/__tests__/theme-provider.js
@@ -1,4 +1,3 @@
-// @flow
/** @jsx jsx */
import 'test-utils/next-env'
import { ignoreConsoleErrors } from 'test-utils'
@@ -57,7 +56,6 @@ cases(
expect(() => {
renderer.create(
- {/* $FlowFixMe */}
({
diff --git a/packages/react/__tests__/use-theme.js b/packages/react/__tests__/use-theme.js
index cbf5d8ca7c..301b5c3f07 100644
--- a/packages/react/__tests__/use-theme.js
+++ b/packages/react/__tests__/use-theme.js
@@ -1,4 +1,3 @@
-// @flow
/** @jsx jsx */
import 'test-utils/next-env'
import * as renderer from 'react-test-renderer'
diff --git a/packages/react/__tests__/warnings.js b/packages/react/__tests__/warnings.js
index 5af566acc0..4a244dc07c 100644
--- a/packages/react/__tests__/warnings.js
+++ b/packages/react/__tests__/warnings.js
@@ -1,4 +1,3 @@
-// @flow
/** @jsx jsx */
import 'test-utils/next-env'
import { jsx, css, Global, keyframes, ClassNames } from '@emotion/react'
@@ -6,7 +5,6 @@ import styled from '@emotion/styled'
import renderer from 'react-test-renderer'
import { render } from '@testing-library/react'
-// $FlowFixMe
console.error = jest.fn()
const validValues = [
@@ -48,7 +46,6 @@ it('does not warn when valid values are passed for the content property', () =>
const invalidValues = ['this is not valid', '', 'element']
it('does warn when invalid values are passed for the content property', () => {
- // $FlowFixMe
invalidValues.forEach(value => {
expect(() =>
renderer.create(
)
@@ -78,7 +75,7 @@ describe('unsafe pseudo classes', () => {
color: hotpink;
}
`
- const match = (pseudoClass.match(/(:first|:nth|:nth-last)-child/): any)
+ const match = pseudoClass.match(/(:first|:nth|:nth-last)-child/)
expect(match).not.toBeNull()
expect(renderer.create(
).toJSON()).toMatchSnapshot()
expect(console.error).toBeCalledWith(
@@ -119,7 +116,7 @@ describe('unsafe pseudo classes', () => {
{ pseudoClass: `:first-child, :nth-child(3)` },
{ pseudoClass: `:first-child:nth-child(3)` }
])('$pseudoClass', ({ pseudoClass }) => {
- const match = (pseudoClass.match(/(:first|:nth|:nth-last)-child/): any)
+ const match = pseudoClass.match(/(:first|:nth|:nth-last)-child/)
expect(match).not.toBeNull()
expect(
renderer.create(
).toJSON()
@@ -145,7 +142,7 @@ describe('unsafe pseudo classes', () => {
)
.toJSON()
).toMatchSnapshot()
- expect((console.error: any).mock.calls).toMatchInlineSnapshot(`
+ expect(console.error.mock.calls).toMatchInlineSnapshot(`
[
[
"The pseudo class ":first-child" is potentially unsafe when doing server-side rendering. Try changing it to ":first-of-type".",
@@ -171,7 +168,7 @@ describe('unsafe pseudo classes', () => {
)
.toJSON()
).toMatchSnapshot()
- expect((console.error: any).mock.calls).toMatchInlineSnapshot(`
+ expect(console.error.mock.calls).toMatchInlineSnapshot(`
[
[
"The pseudo class ":first-child" is potentially unsafe when doing server-side rendering. Try changing it to ":first-of-type".",
@@ -195,7 +192,7 @@ describe('unsafe pseudo classes', () => {
)
.toJSON()
).toMatchSnapshot()
- expect((console.error: any).mock.calls).toMatchInlineSnapshot(`
+ expect(console.error.mock.calls).toMatchInlineSnapshot(`
[
[
"The pseudo class ":first-child" is potentially unsafe when doing server-side rendering. Try changing it to ":first-of-type".",
@@ -219,7 +216,7 @@ describe('unsafe pseudo classes', () => {
)
.toJSON()
).toMatchSnapshot()
- expect((console.error: any).mock.calls).toMatchInlineSnapshot(`
+ expect(console.error.mock.calls).toMatchInlineSnapshot(`
[
[
"The pseudo class ":first-child" is potentially unsafe when doing server-side rendering. Try changing it to ":first-of-type".",
@@ -242,7 +239,7 @@ describe('unsafe pseudo classes', () => {
)
.toJSON()
).toMatchSnapshot()
- expect((console.error: any).mock.calls).toMatchInlineSnapshot(`
+ expect(console.error.mock.calls).toMatchInlineSnapshot(`
[
[
"The pseudo class ":first-child" is potentially unsafe when doing server-side rendering. Try changing it to ":first-of-type".",
@@ -360,7 +357,7 @@ describe('unsafe pseudo classes', () => {
)
.toJSON()
).toMatchSnapshot()
- expect((console.error: any).mock.calls).toMatchInlineSnapshot(`
+ expect(console.error.mock.calls).toMatchInlineSnapshot(`
[
[
"The pseudo class ":first-child" is potentially unsafe when doing server-side rendering. Try changing it to ":first-of-type".",
@@ -393,7 +390,6 @@ describe('unsafe pseudo classes', () => {
test('global with css prop', () => {
let tree = renderer
.create(
- // $FlowFixMe
{
css({ '@media (min-width 800px)': undefined })
css({ '--primary-color': 'hotpink' })
css({ ':last-of-type': null })
- expect((console.error: any).mock.calls).toMatchInlineSnapshot(`
+ expect(console.error.mock.calls).toMatchInlineSnapshot(`
[
[
"Using kebab-case for css properties in objects is not supported. Did you mean backgroundColor?",
@@ -449,7 +445,7 @@ test('keyframes interpolated into plain string', () => {
renderer.create(
)
- expect((console.error: any).mock.calls).toMatchInlineSnapshot(`
+ expect(console.error.mock.calls).toMatchInlineSnapshot(`
[
[
"\`keyframes\` output got interpolated into plain string, please wrap it with \`css\`.
@@ -492,7 +488,6 @@ test('`css` opaque object passed to `cx` from ', () => {
{({ cx }) => (
', () => {
)
- expect((console.error: any).mock.calls).toMatchInlineSnapshot(`
+ expect(console.error.mock.calls).toMatchInlineSnapshot(`
[
[
"You have passed styles created with \`css\` from \`@emotion/react\` package to the \`cx\`.
@@ -526,7 +521,7 @@ test('@import nested in scoped `css`', () => {
/>
)
- expect((console.error: any).mock.calls).toMatchInlineSnapshot(`
+ expect(console.error.mock.calls).toMatchInlineSnapshot(`
[
[
"\`@import\` rules can't be nested inside other rules. Please move it to the top level and put it before regular rules. Keep in mind that they can only be used within global styles.",
@@ -548,7 +543,7 @@ test('@import prepended with other rules', () => {
/>
)
- expect((console.error: any).mock.calls).toMatchInlineSnapshot(`
+ expect(console.error.mock.calls).toMatchInlineSnapshot(`
[
[
"\`@import\` rules can't be after other rules. Please put your \`@import\` rules before your other rules.",
@@ -567,7 +562,7 @@ test('@import prepended by other @import', () => {
/>
)
- expect((console.error: any).mock.calls).toMatchInlineSnapshot(`[]`)
+ expect(console.error.mock.calls).toMatchInlineSnapshot(`[]`)
})
test('when using `jsx` multiple static children should not result in a key-related warning', () => {
@@ -577,5 +572,5 @@ test('when using `jsx` multiple static children should not result in a key-relat
)
- expect((console.error: any).mock.calls).toMatchInlineSnapshot(`[]`)
+ expect(console.error.mock.calls).toMatchInlineSnapshot(`[]`)
})
diff --git a/packages/react/__tests__/with-theme.js b/packages/react/__tests__/with-theme.js
index 4512dc47e0..95c0b9c989 100644
--- a/packages/react/__tests__/with-theme.js
+++ b/packages/react/__tests__/with-theme.js
@@ -1,10 +1,9 @@
-// @flow
import * as React from 'react'
import * as renderer from 'react-test-renderer'
import { withTheme, ThemeProvider } from '@emotion/react'
test('withTheme works', () => {
- class SomeComponent extends React.Component<{ theme: Object }> {
+ class SomeComponent extends React.Component /* <{ theme: Object }> */ {
render() {
return this.props.theme.color
}
@@ -22,7 +21,7 @@ test('withTheme works', () => {
})
test(`withTheme(Comp) hoists non-react static class properties`, () => {
- class ExampleComponent extends React.Component<*> {
+ class ExampleComponent extends React.Component {
static displayName = 'foo'
static someSpecialStatic = 'bar'
}
@@ -30,14 +29,13 @@ test(`withTheme(Comp) hoists non-react static class properties`, () => {
const ComponentWithTheme = withTheme(ExampleComponent)
expect(ComponentWithTheme.displayName).toBe('WithTheme(foo)')
- // $FlowFixMe hoist-non-react-statics doesn't work with AbstractComponent https://github.com/facebook/flow/issues/7612
expect(ComponentWithTheme.someSpecialStatic).toBe(
ExampleComponent.someSpecialStatic
)
})
it('should forward the ref', () => {
- class SomeComponent extends React.Component<*> {
+ class SomeComponent extends React.Component {
render() {
return this.props.theme.color
}
diff --git a/packages/react/macro.js.flow b/packages/react/macro.js.flow
deleted file mode 100644
index 63ae97e66d..0000000000
--- a/packages/react/macro.js.flow
+++ /dev/null
@@ -1,2 +0,0 @@
-// @flow
-export * from './src/index.js'
diff --git a/packages/react/src/class-names.js b/packages/react/src/class-names.js
index 6252324f22..2e8c8acc73 100644
--- a/packages/react/src/class-names.js
+++ b/packages/react/src/class-names.js
@@ -1,4 +1,3 @@
-// @flow
import * as React from 'react'
import {
getRegisteredStyles,
@@ -11,6 +10,7 @@ import { ThemeContext } from './theming'
import { useInsertionEffectAlwaysWithSyncFallback } from '@emotion/use-insertion-effect-with-fallbacks'
import { isBrowser } from './utils'
+/*
type ClassNameArg =
| string
| boolean
@@ -18,8 +18,9 @@ type ClassNameArg =
| Array
| null
| void
+*/
-let classnames = (args: Array): string => {
+let classnames = (args /*: Array */) /*: string */ => {
let len = args.length
let i = 0
let cls = ''
@@ -67,9 +68,9 @@ let classnames = (args: Array): string => {
return cls
}
function merge(
- registered: Object,
- css: (...args: Array) => string,
- className: string
+ registered /*: Object */,
+ css /*: (...args: Array) => string */,
+ className /*: string */
) {
const registeredStyles = []
@@ -85,14 +86,6 @@ function merge(
return rawClassName + css(registeredStyles)
}
-type Props = {
- children: ({
- css: (...args: any) => string,
- cx: (...args: Array) => string,
- theme: Object
- }) => React.Node
-}
-
const Insertion = ({ cache, serializedArr }) => {
let rules = useInsertionEffectAlwaysWithSyncFallback(() => {
let rules = ''
@@ -123,12 +116,21 @@ const Insertion = ({ cache, serializedArr }) => {
return null
}
-export const ClassNames: React.AbstractComponent =
+/*
+type Props = {
+ children: ({
+ css: (...args: any) => string,
+ cx: (...args: Array) => string,
+ theme: Object
+ }) => React.Node
+} */
+
+export const ClassNames /*: React.AbstractComponent*/ =
/* #__PURE__ */ withEmotionCache((props, cache) => {
let hasRendered = false
let serializedArr = []
- let css = (...args: Array) => {
+ let css = (...args /*: Array */) => {
if (hasRendered && process.env.NODE_ENV !== 'production') {
throw new Error('css can only be used during render')
}
@@ -139,7 +141,7 @@ export const ClassNames: React.AbstractComponent =
registerStyles(cache, serialized, false)
return `${cache.key}-${serialized.name}`
}
- let cx = (...args: Array) => {
+ let cx = (...args /*: Array*/) => {
if (hasRendered && process.env.NODE_ENV !== 'production') {
throw new Error('cx can only be used during render')
}
diff --git a/packages/react/src/context.js b/packages/react/src/context.js
index e74d4de212..ccf4e0f24c 100644
--- a/packages/react/src/context.js
+++ b/packages/react/src/context.js
@@ -1,11 +1,10 @@
-// @flow
-import { type EmotionCache } from '@emotion/utils'
+/* import { type EmotionCache } from '@emotion/utils' */
import * as React from 'react'
import { useContext, forwardRef } from 'react'
import createCache from '@emotion/cache'
import { isBrowser } from './utils'
-let EmotionCacheContext: React.Context =
+let EmotionCacheContext /*: React.Context */ =
/* #__PURE__ */ React.createContext(
// we're doing this to avoid preconstruct's dead code elimination in this one case
// because this module is primarily intended for the browser and node
@@ -25,27 +24,27 @@ if (process.env.NODE_ENV !== 'production') {
export let CacheProvider = EmotionCacheContext.Provider
export let __unsafe_useEmotionCache =
- function useEmotionCache(): EmotionCache | null {
+ function useEmotionCache() /*: EmotionCache | null*/ {
return useContext(EmotionCacheContext)
}
-let withEmotionCache = function withEmotionCache>(
- func: (props: Props, cache: EmotionCache, ref: Ref) => React.Node
-): React.AbstractComponent {
- // $FlowFixMe
- return forwardRef((props: Props, ref: Ref) => {
- // the cache will never be null in the browser
- let cache = ((useContext(EmotionCacheContext): any): EmotionCache)
+let withEmotionCache =
+ function withEmotionCache /* > */(
+ func /*: (props: Props, cache: EmotionCache, ref: Ref) => React.Node */
+ ) /*: React.AbstractComponent */ {
+ return forwardRef((props /*: Props */, ref /*: Ref */) => {
+ // the cache will never be null in the browser
+ let cache = useContext(EmotionCacheContext)
- return func(props, cache, ref)
- })
-}
+ return func(props, cache, ref)
+ })
+ }
if (!isBrowser) {
- withEmotionCache = function withEmotionCache(
- func: (props: Props, cache: EmotionCache) => React.Node
- ): React.StatelessFunctionalComponent {
- return (props: Props) => {
+ withEmotionCache = function withEmotionCache /* */(
+ func /*: (props: Props, cache: EmotionCache) => React.Node */
+ ) /*: React.StatelessFunctionalComponent */ {
+ return (props /*: Props */) => {
let cache = useContext(EmotionCacheContext)
if (cache === null) {
// yes, we're potentially creating this on every render
diff --git a/packages/react/src/css.js b/packages/react/src/css.js
index ac79c1dfa3..785320e8f1 100644
--- a/packages/react/src/css.js
+++ b/packages/react/src/css.js
@@ -1,9 +1,7 @@
-// @flow
-
-import type { Interpolation, SerializedStyles } from '@emotion/utils'
+/* import type { Interpolation, SerializedStyles } from '@emotion/utils' */
import { serializeStyles } from '@emotion/serialize'
-function css(...args: Array): SerializedStyles {
+function css(...args /*: Array */) /*: SerializedStyles */ {
return serializeStyles(args)
}
diff --git a/packages/react/src/emotion-element.js b/packages/react/src/emotion-element.js
index 0ae4c4b64c..211dbac662 100644
--- a/packages/react/src/emotion-element.js
+++ b/packages/react/src/emotion-element.js
@@ -1,4 +1,3 @@
-// @flow
import * as React from 'react'
import { withEmotionCache } from './context'
import { ThemeContext } from './theming'
@@ -16,7 +15,10 @@ let typePropName = '__EMOTION_TYPE_PLEASE_DO_NOT_USE__'
let labelPropName = '__EMOTION_LABEL_PLEASE_DO_NOT_USE__'
-export const createEmotionProps = (type: React.ElementType, props: Object) => {
+export const createEmotionProps = (
+ type /*: React.ElementType */,
+ props /*: Object */
+) => {
if (
process.env.NODE_ENV !== 'production' &&
typeof props.css === 'string' &&
@@ -28,7 +30,7 @@ export const createEmotionProps = (type: React.ElementType, props: Object) => {
)
}
- let newProps: any = {}
+ let newProps /*: any */ = {}
for (let key in props) {
if (hasOwn.call(props, key)) {
@@ -81,8 +83,8 @@ const Insertion = ({ cache, serialized, isStringTag }) => {
return null
}
-let Emotion = /* #__PURE__ */ withEmotionCache(
- (props, cache, ref) => {
+let Emotion = /* #__PURE__ */ withEmotionCache(
+ /* */ (props, cache, ref) => {
let cssProp = props.css
// so that using `css` from `emotion` and passing the result to the css prop works
diff --git a/packages/react/src/get-label-from-stack-trace.js b/packages/react/src/get-label-from-stack-trace.js
index c356b14e16..5d0dcd5bcb 100644
--- a/packages/react/src/get-label-from-stack-trace.js
+++ b/packages/react/src/get-label-from-stack-trace.js
@@ -1,13 +1,11 @@
-// @flow
-
-const getLastPart = (functionName: string): string => {
+const getLastPart = (functionName /* : string */) /* : string */ => {
// The match may be something like 'Object.createEmotionProps' or
// 'Loader.prototype.render'
const parts = functionName.split('.')
return parts[parts.length - 1]
}
-const getFunctionNameFromStackTraceLine = (line: string): ?string => {
+const getFunctionNameFromStackTraceLine = (line /*: string*/) /*: ?string*/ => {
// V8
let match = /^\s+at\s+([A-Za-z0-9$.]+)\s/.exec(line)
if (match) return getLastPart(match[1])
@@ -29,10 +27,9 @@ const internalReactFunctionNames = /* #__PURE__ */ new Set([
// These identifiers come from error stacks, so they have to be valid JS
// identifiers, thus we only need to replace what is a valid character for JS,
// but not for CSS.
-const sanitizeIdentifier = (identifier: string) =>
- identifier.replace(/\$/g, '-')
+const sanitizeIdentifier = identifier => identifier.replace(/\$/g, '-')
-export const getLabelFromStackTrace = (stackTrace: string): ?string => {
+export const getLabelFromStackTrace = stackTrace => {
if (!stackTrace) return undefined
const lines = stackTrace.split('\n')
diff --git a/packages/react/src/global.js b/packages/react/src/global.js
index bcbbbd2b04..48041e96ec 100644
--- a/packages/react/src/global.js
+++ b/packages/react/src/global.js
@@ -1,4 +1,3 @@
-// @flow
import * as React from 'react'
import { withEmotionCache } from './context'
import { ThemeContext } from './theming'
@@ -8,11 +7,13 @@ import { useInsertionEffectWithLayoutFallback } from '@emotion/use-insertion-eff
import { serializeStyles } from '@emotion/serialize'
+/*
type Styles = Object | Array
type GlobalProps = {
+styles: Styles | (Object => Styles)
}
+*/
let warnedAboutCssPropForGlobal = false
@@ -20,123 +21,123 @@ let warnedAboutCssPropForGlobal = false
// initial render from browser, insertBefore context.sheet.tags[0] or if a style hasn't been inserted there yet, appendChild
// initial client-side render from SSR, use place of hydrating tag
-export let Global: React.AbstractComponent =
- /* #__PURE__ */ withEmotionCache((props: GlobalProps, cache) => {
- if (
- process.env.NODE_ENV !== 'production' &&
- !warnedAboutCssPropForGlobal && // check for className as well since the user is
- // probably using the custom createElement which
- // means it will be turned into a className prop
- // $FlowFixMe I don't really want to add it to the type since it shouldn't be used
- (props.className || props.css)
- ) {
- console.error(
- "It looks like you're using the css prop on Global, did you mean to use the styles prop instead?"
- )
- warnedAboutCssPropForGlobal = true
+export let Global /*: React.AbstractComponent<
+ GlobalProps
+> */ = /* #__PURE__ */ withEmotionCache((props /*: GlobalProps */, cache) => {
+ if (
+ process.env.NODE_ENV !== 'production' &&
+ !warnedAboutCssPropForGlobal && // check for className as well since the user is
+ // probably using the custom createElement which
+ // means it will be turned into a className prop
+ // I don't really want to add it to the type since it shouldn't be used
+ (props.className || props.css)
+ ) {
+ console.error(
+ "It looks like you're using the css prop on Global, did you mean to use the styles prop instead?"
+ )
+ warnedAboutCssPropForGlobal = true
+ }
+ let styles = props.styles
+
+ let serialized = serializeStyles(
+ [styles],
+ undefined,
+ React.useContext(ThemeContext)
+ )
+
+ if (!isBrowser) {
+ let serializedNames = serialized.name
+ let serializedStyles = serialized.styles
+ let next = serialized.next
+ while (next !== undefined) {
+ serializedNames += ' ' + next.name
+ serializedStyles += next.styles
+ next = next.next
+ }
+
+ let shouldCache = cache.compat === true
+
+ let rules = cache.insert(
+ ``,
+ { name: serializedNames, styles: serializedStyles },
+ cache.sheet,
+ shouldCache
+ )
+
+ if (shouldCache) {
+ return null
}
- let styles = props.styles
- let serialized = serializeStyles(
- [styles],
- undefined,
- React.useContext(ThemeContext)
+ return (
+
)
+ }
+
+ // yes, i know these hooks are used conditionally
+ // but it is based on a constant that will never change at runtime
+ // it's effectively like having two implementations and switching them out
+ // so it's not actually breaking anything
+
+ let sheetRef = React.useRef()
+
+ useInsertionEffectWithLayoutFallback(() => {
+ const key = `${cache.key}-global`
+
+ // use case of https://github.com/emotion-js/emotion/issues/2675
+ let sheet = new cache.sheet.constructor({
+ key,
+ nonce: cache.sheet.nonce,
+ container: cache.sheet.container,
+ speedy: cache.sheet.isSpeedy
+ })
+ let rehydrating = false
+ let node /*: HTMLStyleElement | null*/ = document.querySelector(
+ `style[data-emotion="${key} ${serialized.name}"]`
+ )
+ if (cache.sheet.tags.length) {
+ sheet.before = cache.sheet.tags[0]
+ }
+ if (node !== null) {
+ rehydrating = true
+ // clear the hash so this node won't be recognizable as rehydratable by other s
+ node.setAttribute('data-emotion', key)
+ sheet.hydrate([node])
+ }
+ sheetRef.current = [sheet, rehydrating]
+ return () => {
+ sheet.flush()
+ }
+ }, [cache])
+
+ useInsertionEffectWithLayoutFallback(() => {
+ let sheetRefCurrent = sheetRef.current
+ let [sheet, rehydrating] = sheetRefCurrent
+ if (rehydrating) {
+ sheetRefCurrent[1] = false
+ return
+ }
+ if (serialized.next !== undefined) {
+ // insert keyframes
+ insertStyles(cache, serialized.next, true)
+ }
- if (!isBrowser) {
- let serializedNames = serialized.name
- let serializedStyles = serialized.styles
- let next = serialized.next
- while (next !== undefined) {
- serializedNames += ' ' + next.name
- serializedStyles += next.styles
- next = next.next
- }
-
- let shouldCache = cache.compat === true
-
- let rules = cache.insert(
- ``,
- { name: serializedNames, styles: serializedStyles },
- cache.sheet,
- shouldCache
- )
-
- if (shouldCache) {
- return null
- }
-
- return (
-
- )
+ if (sheet.tags.length) {
+ // if this doesn't exist then it will be null so the style element will be appended
+ let element = sheet.tags[sheet.tags.length - 1].nextElementSibling
+ sheet.before = element
+ sheet.flush()
}
+ cache.insert(``, serialized, sheet, false)
+ }, [cache, serialized.name])
- // yes, i know these hooks are used conditionally
- // but it is based on a constant that will never change at runtime
- // it's effectively like having two implementations and switching them out
- // so it's not actually breaking anything
-
- let sheetRef = React.useRef()
-
- useInsertionEffectWithLayoutFallback(() => {
- const key = `${cache.key}-global`
-
- // use case of https://github.com/emotion-js/emotion/issues/2675
- let sheet = new cache.sheet.constructor({
- key,
- nonce: cache.sheet.nonce,
- container: cache.sheet.container,
- speedy: cache.sheet.isSpeedy
- })
- let rehydrating = false
- // $FlowFixMe
- let node: HTMLStyleElement | null = document.querySelector(
- `style[data-emotion="${key} ${serialized.name}"]`
- )
- if (cache.sheet.tags.length) {
- sheet.before = cache.sheet.tags[0]
- }
- if (node !== null) {
- rehydrating = true
- // clear the hash so this node won't be recognizable as rehydratable by other s
- node.setAttribute('data-emotion', key)
- sheet.hydrate([node])
- }
- sheetRef.current = [sheet, rehydrating]
- return () => {
- sheet.flush()
- }
- }, [cache])
-
- useInsertionEffectWithLayoutFallback(() => {
- let sheetRefCurrent = (sheetRef.current: any)
- let [sheet, rehydrating] = sheetRefCurrent
- if (rehydrating) {
- sheetRefCurrent[1] = false
- return
- }
- if (serialized.next !== undefined) {
- // insert keyframes
- insertStyles(cache, serialized.next, true)
- }
-
- if (sheet.tags.length) {
- // if this doesn't exist then it will be null so the style element will be appended
- let element = sheet.tags[sheet.tags.length - 1].nextElementSibling
- sheet.before = ((element: any): Element | null)
- sheet.flush()
- }
- cache.insert(``, serialized, sheet, false)
- }, [cache, serialized.name])
-
- return null
- })
+ return null
+})
if (process.env.NODE_ENV !== 'production') {
Global.displayName = 'EmotionGlobal'
diff --git a/packages/react/src/index.js b/packages/react/src/index.js
index 3b4a3ad6af..52addae9d6 100644
--- a/packages/react/src/index.js
+++ b/packages/react/src/index.js
@@ -1,6 +1,5 @@
-// @flow
import pkg from '../package.json'
-export type { SerializedStyles } from '@emotion/utils'
+// export type { SerializedStyles } from '@emotion/utils'
export {
withEmotionCache,
CacheProvider,
diff --git a/packages/react/src/jsx-dev-runtime.js b/packages/react/src/jsx-dev-runtime.js
index 9b402438a4..42f7df1f91 100644
--- a/packages/react/src/jsx-dev-runtime.js
+++ b/packages/react/src/jsx-dev-runtime.js
@@ -1,18 +1,10 @@
-// @flow
import * as ReactJSXRuntimeDev from 'react/jsx-dev-runtime'
import Emotion, { createEmotionProps } from './emotion-element'
import { hasOwn } from './utils'
export const Fragment = ReactJSXRuntimeDev.Fragment
-export function jsxDEV(
- type: any,
- props: any,
- key: any,
- isStaticChildren: any,
- source: any,
- self: any
-) {
+export function jsxDEV(type, props, key, isStaticChildren, source, self) {
if (!hasOwn.call(props, 'css')) {
return ReactJSXRuntimeDev.jsxDEV(
type,
diff --git a/packages/react/src/jsx-runtime.js b/packages/react/src/jsx-runtime.js
index d212d4b0f3..9f992bef12 100644
--- a/packages/react/src/jsx-runtime.js
+++ b/packages/react/src/jsx-runtime.js
@@ -1,11 +1,10 @@
-// @flow
import * as ReactJSXRuntime from 'react/jsx-runtime'
import Emotion, { createEmotionProps } from './emotion-element'
import { hasOwn } from './utils'
export const Fragment = ReactJSXRuntime.Fragment
-export function jsx(type: any, props: any, key: any) {
+export function jsx(type, props, key) {
if (!hasOwn.call(props, 'css')) {
return ReactJSXRuntime.jsx(type, props, key)
}
@@ -13,7 +12,7 @@ export function jsx(type: any, props: any, key: any) {
return ReactJSXRuntime.jsx(Emotion, createEmotionProps(type, props), key)
}
-export function jsxs(type: any, props: any, key: any) {
+export function jsxs(type, props, key) {
if (!hasOwn.call(props, 'css')) {
return ReactJSXRuntime.jsxs(type, props, key)
}
diff --git a/packages/react/src/jsx.js b/packages/react/src/jsx.js
index 7e27f84c4e..4fb065653b 100644
--- a/packages/react/src/jsx.js
+++ b/packages/react/src/jsx.js
@@ -1,17 +1,14 @@
-// @flow
import * as React from 'react'
import Emotion, { createEmotionProps } from './emotion-element'
import { hasOwn } from './utils'
-// $FlowFixMe
-export const jsx: typeof React.createElement = function (
- type: React.ElementType,
- props: Object
+export const jsx /*: typeof React.createElement */ = function (
+ type /*: React.ElementType */,
+ props /*: Object */
) {
let args = arguments
if (props == null || !hasOwn.call(props, 'css')) {
- // $FlowFixMe
return React.createElement.apply(undefined, args)
}
@@ -24,6 +21,5 @@ export const jsx: typeof React.createElement = function (
createElementArgArray[i] = args[i]
}
- // $FlowFixMe
return React.createElement.apply(null, createElementArgArray)
}
diff --git a/packages/react/src/keyframes.js b/packages/react/src/keyframes.js
index b02b670a42..2f1d13174e 100644
--- a/packages/react/src/keyframes.js
+++ b/packages/react/src/keyframes.js
@@ -1,17 +1,17 @@
-// @flow
import css from './css'
+/*
type Keyframes = {|
name: string,
styles: string,
anim: 1,
toString: () => string
|} & string
+*/
-export const keyframes = (...args: *): Keyframes => {
+export const keyframes = (...args) /*: Keyframes */ => {
let insertable = css(...args)
const name = `animation-${insertable.name}`
- // $FlowFixMe
return {
name,
styles: `@keyframes ${name}{${insertable.styles}}`,
diff --git a/packages/react/src/theming.js b/packages/react/src/theming.js
index 972b5b5d7f..ba7e91ef19 100644
--- a/packages/react/src/theming.js
+++ b/packages/react/src/theming.js
@@ -1,16 +1,18 @@
-// @flow
import * as React from 'react'
import weakMemoize from '@emotion/weak-memoize'
import hoistNonReactStatics from './_isolated-hnrs'
-export const ThemeContext = /* #__PURE__ */ React.createContext({})
+export const ThemeContext = /* #__PURE__ */ React.createContext({})
if (process.env.NODE_ENV !== 'production') {
ThemeContext.displayName = 'EmotionThemeContext'
}
export const useTheme = () => React.useContext(ThemeContext)
-const getTheme = (outerTheme: Object, theme: Object | (Object => Object)) => {
+const getTheme = (
+ outerTheme /*: Object */,
+ theme /*: Object | (Object => Object) */
+) => {
if (typeof theme === 'function') {
const mergedTheme = theme(outerTheme)
if (
@@ -43,12 +45,14 @@ let createCacheWithTheme = /* #__PURE__ */ weakMemoize(outerTheme => {
})
})
+/*
type ThemeProviderProps = {
theme: Object | (Object => Object),
children: React.Node
}
+*/
-export const ThemeProvider = (props: ThemeProviderProps) => {
+export const ThemeProvider = (props /*: ThemeProviderProps */) => {
let theme = React.useContext(ThemeContext)
if (props.theme !== theme) {
@@ -61,16 +65,15 @@ export const ThemeProvider = (props: ThemeProviderProps) => {
)
}
-export function withTheme(
- Component: React.AbstractComponent
-): React.AbstractComponent<$Diff> {
+export function withTheme /* */(
+ Component /*: React.AbstractComponent */
+) /*: React.AbstractComponent<$Diff> */ {
const componentName = Component.displayName || Component.name || 'Component'
let render = (props, ref) => {
let theme = React.useContext(ThemeContext)
return
}
- // $FlowFixMe
let WithTheme = React.forwardRef(render)
WithTheme.displayName = `WithTheme(${componentName})`
diff --git a/packages/react/src/utils.js b/packages/react/src/utils.js
index 305c0a1f66..5cb7b5d00c 100644
--- a/packages/react/src/utils.js
+++ b/packages/react/src/utils.js
@@ -1,4 +1,3 @@
-// @flow
export let isBrowser = typeof document !== 'undefined'
export const hasOwn = {}.hasOwnProperty
diff --git a/packages/serialize/package.json b/packages/serialize/package.json
index 10a23ff928..d628a0e84a 100644
--- a/packages/serialize/package.json
+++ b/packages/serialize/package.json
@@ -4,7 +4,7 @@
"description": "serialization utils for emotion",
"main": "dist/emotion-serialize.cjs.js",
"module": "dist/emotion-serialize.esm.js",
- "types": "types/index.d.ts",
+ "types": "dist/emotion-serialize.cjs.d.ts",
"license": "MIT",
"repository": "https://github.com/emotion-js/emotion/tree/main/packages/serialize",
"publishConfig": {
@@ -26,8 +26,7 @@
},
"files": [
"src",
- "dist",
- "types/*.d.ts"
+ "dist"
],
"browser": {
"./dist/emotion-serialize.esm.js": "./dist/emotion-serialize.browser.esm.js"
diff --git a/packages/serialize/src/index.d.ts b/packages/serialize/src/index.d.ts
deleted file mode 100644
index 9e46093759..0000000000
--- a/packages/serialize/src/index.d.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from '../types'
-export { default } from '../types'
diff --git a/packages/serialize/src/index.js b/packages/serialize/src/index.ts
similarity index 64%
rename from packages/serialize/src/index.js
rename to packages/serialize/src/index.ts
index 8352ba935b..b0ea8e1d25 100644
--- a/packages/serialize/src/index.js
+++ b/packages/serialize/src/index.ts
@@ -1,12 +1,73 @@
-// @flow
-import type {
- Interpolation,
- SerializedStyles,
- RegisteredCache
-} from '@emotion/utils'
+import type { RegisteredCache, SerializedStyles } from '@emotion/utils'
import hashString from '@emotion/hash'
import unitless from '@emotion/unitless'
import memoize from '@emotion/memoize'
+import * as CSS from 'csstype'
+
+export type { RegisteredCache, SerializedStyles }
+
+type Cursor = {
+ name: string
+ styles: string
+ next?: Cursor
+}
+
+export type CSSProperties = CSS.PropertiesFallback
+export type CSSPropertiesWithMultiValues = {
+ [K in keyof CSSProperties]:
+ | CSSProperties[K]
+ | ReadonlyArray>
+}
+
+export type CSSPseudos = { [K in CSS.Pseudos]?: CSSObject }
+
+export interface ArrayCSSInterpolation
+ extends ReadonlyArray {}
+
+export type InterpolationPrimitive =
+ | null
+ | undefined
+ | boolean
+ | number
+ | string
+ | ComponentSelector
+ | Keyframes
+ | SerializedStyles
+ | CSSObject
+
+export type CSSInterpolation = InterpolationPrimitive | ArrayCSSInterpolation
+
+export interface CSSOthersObject {
+ [propertiesName: string]: CSSInterpolation
+}
+
+export interface CSSObject
+ extends CSSPropertiesWithMultiValues,
+ CSSPseudos,
+ CSSOthersObject {}
+
+export interface ComponentSelector {
+ __emotion_styles: any
+}
+
+export type Keyframes = {
+ name: string
+ styles: string
+ anim: number
+ toString: () => string
+} & string
+
+export interface ArrayInterpolation
+ extends ReadonlyArray> {}
+
+export interface FunctionInterpolation {
+ (props: Props): Interpolation
+}
+
+export type Interpolation =
+ | InterpolationPrimitive
+ | ArrayInterpolation
+ | FunctionInterpolation
const ILLEGAL_ESCAPE_SEQUENCE_ERROR = `You have illegal escape sequence in your template literal, most likely inside content's property value.
Because you write your CSS inside a JavaScript string you actually have to do double escaping, so for example "content: '\\00d7';" should become "content: '\\\\00d7';".
@@ -20,7 +81,8 @@ let hyphenateRegex = /[A-Z]|^ms/g
let animationRegex = /_EMO_([^_]+?)_([^]*?)_EMO_/g
const isCustomProperty = (property: string) => property.charCodeAt(1) === 45
-const isProcessableValue = value => value != null && typeof value !== 'boolean'
+const isProcessableValue = (value: Interpolation) =>
+ value != null && typeof value !== 'boolean'
const processStyleName = /* #__PURE__ */ memoize((styleName: string) =>
isCustomProperty(styleName)
@@ -49,7 +111,7 @@ let processStyleValue = (
}
if (
- unitless[key] !== 1 &&
+ unitless[key as keyof typeof unitless] !== 1 &&
!isCustomProperty(key) &&
typeof value === 'number' &&
value !== 0
@@ -69,9 +131,9 @@ if (process.env.NODE_ENV !== 'production') {
let msPattern = /^-ms-/
let hyphenPattern = /-(.)/g
- let hyphenatedCache = {}
+ let hyphenatedCache: Record = {}
- processStyleValue = (key: string, value: string) => {
+ processStyleValue = (key: string, value: string | number) => {
if (key === 'content') {
if (
typeof value !== 'string' ||
@@ -112,21 +174,22 @@ const noComponentSelectorMessage =
'compiler transform.'
function handleInterpolation(
- mergedProps: void | Object,
- registered: RegisteredCache | void,
+ mergedProps: unknown | undefined,
+ registered: RegisteredCache | undefined,
interpolation: Interpolation
): string | number {
if (interpolation == null) {
return ''
}
- if (interpolation.__emotion_styles !== undefined) {
+ const componentSelector = interpolation as ComponentSelector
+ if (componentSelector.__emotion_styles !== undefined) {
if (
process.env.NODE_ENV !== 'production' &&
- interpolation.toString() === 'NO_COMPONENT_SELECTOR'
+ String(componentSelector) === 'NO_COMPONENT_SELECTOR'
) {
throw new Error(noComponentSelectorMessage)
}
- return interpolation
+ return componentSelector as unknown as string
}
switch (typeof interpolation) {
@@ -134,17 +197,19 @@ function handleInterpolation(
return ''
}
case 'object': {
- if (interpolation.anim === 1) {
+ const keyframes = interpolation as Keyframes
+ if (keyframes.anim === 1) {
cursor = {
- name: interpolation.name,
- styles: interpolation.styles,
+ name: keyframes.name,
+ styles: keyframes.styles,
next: cursor
}
- return interpolation.name
+ return keyframes.name
}
- if (interpolation.styles !== undefined) {
- let next = interpolation.next
+ const serializedStyles = interpolation as SerializedStyles
+ if (serializedStyles.styles !== undefined) {
+ let next = serializedStyles.next
if (next !== undefined) {
// not the most efficient thing ever but this is a pretty rare case
// and there will be very few iterations of this generally
@@ -157,18 +222,22 @@ function handleInterpolation(
next = next.next
}
}
- let styles = `${interpolation.styles};`
+ let styles = `${serializedStyles.styles};`
if (
process.env.NODE_ENV !== 'production' &&
- interpolation.map !== undefined
+ serializedStyles.map !== undefined
) {
- styles += interpolation.map
+ styles += serializedStyles.map
}
return styles
}
- return createStringFromObject(mergedProps, registered, interpolation)
+ return createStringFromObject(
+ mergedProps,
+ registered,
+ interpolation as ArrayInterpolation | CSSObject
+ )
}
case 'function': {
if (mergedProps !== undefined) {
@@ -190,10 +259,10 @@ function handleInterpolation(
}
case 'string':
if (process.env.NODE_ENV !== 'production') {
- const matched = []
+ const matched: string[] = []
const replaced = interpolation.replace(
animationRegex,
- (match, p1, p2) => {
+ (_match, _p1, p2) => {
const fakeVarName = `animation${matched.length}`
matched.push(
`const ${fakeVarName} = keyframes\`${p2.replace(
@@ -206,11 +275,15 @@ function handleInterpolation(
)
if (matched.length) {
console.error(
- '`keyframes` output got interpolated into plain string, please wrap it with `css`.\n\n' +
- 'Instead of doing this:\n\n' +
- [...matched, `\`${replaced}\``].join('\n') +
- '\n\nYou should wrap it with `css` like this:\n\n' +
- `css\`${replaced}\``
+ `\`keyframes\` output got interpolated into plain string, please wrap it with \`css\`.
+
+Instead of doing this:
+
+${[...matched, `\`${replaced}\``].join('\n')}
+
+You should wrap it with \`css\` like this:
+
+css\`${replaced}\``
)
}
}
@@ -218,17 +291,18 @@ function handleInterpolation(
}
// finalize string values (regular strings and functions interpolated into css calls)
+ const asString = interpolation as string
if (registered == null) {
- return interpolation
+ return asString
}
- const cached = registered[interpolation]
- return cached !== undefined ? cached : interpolation
+ const cached = registered[asString]
+ return cached !== undefined ? cached : asString
}
function createStringFromObject(
- mergedProps: void | Object,
- registered: RegisteredCache | void,
- obj: { [key: string]: Interpolation }
+ mergedProps: unknown | undefined,
+ registered: RegisteredCache | undefined,
+ obj: ArrayInterpolation | CSSObject
): string {
let string = ''
@@ -238,12 +312,16 @@ function createStringFromObject(
}
} else {
for (let key in obj) {
- let value = obj[key]
+ let value: unknown = obj[key as never]
if (typeof value !== 'object') {
- if (registered != null && registered[value] !== undefined) {
- string += `${key}{${registered[value]}}`
- } else if (isProcessableValue(value)) {
- string += `${processStyleName(key)}:${processStyleValue(key, value)};`
+ const asString = value as string
+ if (registered != null && registered[asString] !== undefined) {
+ string += `${key}{${registered[asString]}}`
+ } else if (isProcessableValue(asString)) {
+ string += `${processStyleName(key)}:${processStyleValue(
+ key,
+ asString
+ )};`
}
} else {
if (
@@ -261,7 +339,7 @@ function createStringFromObject(
if (isProcessableValue(value[i])) {
string += `${processStyleName(key)}:${processStyleValue(
key,
- value[i]
+ value[i] as string | number
)};`
}
}
@@ -269,7 +347,7 @@ function createStringFromObject(
const interpolated = handleInterpolation(
mergedProps,
registered,
- value
+ value as Interpolation
)
switch (key) {
case 'animation':
@@ -297,7 +375,7 @@ function createStringFromObject(
let labelPattern = /label:\s*([^\s;\n{]+)\s*(;|$)/g
-let sourceMapPattern
+let sourceMapPattern: RegExp | undefined
if (process.env.NODE_ENV !== 'production') {
sourceMapPattern =
/\/\*#\ssourceMappingURL=data:application\/json;\S+\s+\*\//g
@@ -305,49 +383,70 @@ if (process.env.NODE_ENV !== 'production') {
// this is the cursor for keyframes
// keyframes are stored on the SerializedStyles object as a linked list
-let cursor
-
-export const serializeStyles = function (
- args: Array,
- registered: RegisteredCache | void,
- mergedProps: void | Object
+let cursor: Cursor | undefined
+
+export function serializeStyles(
+ args: Array>,
+ registered?: RegisteredCache,
+ mergedProps?: Props
+): SerializedStyles
+export function serializeStyles(
+ args: Array>,
+ registered?: RegisteredCache,
+ mergedProps?: unknown
): SerializedStyles {
if (
args.length === 1 &&
typeof args[0] === 'object' &&
args[0] !== null &&
- args[0].styles !== undefined
+ (args[0] as SerializedStyles).styles !== undefined
) {
- return args[0]
+ return args[0] as SerializedStyles
}
let stringMode = true
let styles = ''
cursor = undefined
let strings = args[0]
- if (strings == null || strings.raw === undefined) {
+ if (strings == null || (strings as TemplateStringsArray).raw === undefined) {
stringMode = false
- styles += handleInterpolation(mergedProps, registered, strings)
+ styles += handleInterpolation(
+ mergedProps,
+ registered,
+ strings as Interpolation
+ )
} else {
- if (process.env.NODE_ENV !== 'production' && strings[0] === undefined) {
+ const asTemplateStringsArr = strings as TemplateStringsArray
+ if (
+ process.env.NODE_ENV !== 'production' &&
+ asTemplateStringsArr[0] === undefined
+ ) {
console.error(ILLEGAL_ESCAPE_SEQUENCE_ERROR)
}
- styles += strings[0]
+ styles += asTemplateStringsArr[0]
}
// we start at 1 since we've already handled the first arg
for (let i = 1; i < args.length; i++) {
- styles += handleInterpolation(mergedProps, registered, args[i])
+ styles += handleInterpolation(
+ mergedProps,
+ registered,
+ args[i] as Interpolation
+ )
if (stringMode) {
- if (process.env.NODE_ENV !== 'production' && strings[i] === undefined) {
+ const templateStringsArr = strings as TemplateStringsArray
+ if (
+ process.env.NODE_ENV !== 'production' &&
+ templateStringsArr[i] === undefined
+ ) {
console.error(ILLEGAL_ESCAPE_SEQUENCE_ERROR)
}
- styles += strings[i]
+ styles += templateStringsArr[i]
}
}
let sourceMap
if (process.env.NODE_ENV !== 'production') {
- styles = styles.replace(sourceMapPattern, match => {
+ styles = styles.replace(sourceMapPattern!, match => {
sourceMap = match
return ''
})
@@ -360,17 +459,13 @@ export const serializeStyles = function (
let match
// https://esbench.com/bench/5b809c2cf2949800a0f61fb5
while ((match = labelPattern.exec(styles)) !== null) {
- identifierName +=
- '-' +
- // $FlowFixMe we know it's not null
- match[1]
+ identifierName += '-' + match[1]
}
let name = hashString(styles) + identifierName
if (process.env.NODE_ENV !== 'production') {
- // $FlowFixMe SerializedStyles type doesn't have toString property (and we don't want to add it)
- return {
+ const devStyles = {
name,
styles,
map: sourceMap,
@@ -379,6 +474,7 @@ export const serializeStyles = function (
return "You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."
}
}
+ return devStyles
}
return {
name,
diff --git a/packages/serialize/types/index.d.ts b/packages/serialize/types/index.d.ts
index 1971b748b7..f3ec2718c3 100644
--- a/packages/serialize/types/index.d.ts
+++ b/packages/serialize/types/index.d.ts
@@ -1,70 +1,3 @@
-// Definitions by: Junyoung Clare Jang
-// TypeScript Version: 2.8
+///