Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

emotion

Package Overview
Dependencies
Maintainers
2
Versions
144
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

emotion - npm Package Compare versions

Comparing version 2.0.1 to 3.0.0

src/attrs.js

2

babel.js

@@ -1,1 +0,1 @@

module.exports = require('./src/babel')
module.exports = require('./lib/babel')
{
"name": "emotion",
"version": "2.0.1",
"version": "3.0.0",
"description": "👩‍🎤 Glam + React",
"jsnext:main": "dist/emotion.es.js",
"module": "dist/emotion.es.js",
"main": "dist/glam.js",
"umd:main": "dist/emotion.umd.js",
"module": "src/index.js",
"main": "lib/index.js",
"files": [

@@ -15,15 +13,18 @@ "babel.js",

"scripts": {
"build": "npm-run-all clean -p rollup -p minify:* -s size",
"build": "babel src -d lib",
"build:watch": "npm run build -- -w",
"umd": "npm-run-all clean -p rollup -p minify:* -s size",
"clean": "rimraf dist",
"test": "standard src test && jest --coverage",
"test:watch": "jest --watch",
"test": "standard src test && jest --coverage --no-cache",
"test:watch": "jest --watch --no-cache",
"rollup": "rollup -c",
"minify:cjs": "uglifyjs $npm_package_main -cm toplevel -o $npm_package_main -p relative --in-source-map ${npm_package_main}.map --source-map ${npm_package_main}.map",
"minify:umd": "uglifyjs $npm_package_umd_main -cm -o $npm_package_umd_main -p relative --in-source-map ${npm_package_umd_main}.map --source-map ${npm_package_umd_main}.map",
"size": "echo \"Gzipped Size: $(strip-json-comments --no-whitespace $npm_package_main | gzip-size)\"",
"release": "npm run test && npm run build && npm version patch && npm publish && git push --tags"
"size": "echo \"Gzipped Size: $(strip-json-comments --no-whitespace $npm_package_umd_main | gzip-size)\"",
"release": "npm run test && npm run build && npm version patch && npm publish && git push --tags",
"lint": "standard --fix",
"format": "prettier-eslint --write \"src/**/*.js\" \"test/**/*.js\" \"example/**/*.js\" \"jest-utils/**/*.js\""
},
"dependencies": {
"babel-plugin-syntax-jsx": "^6.18.0",
"glam": "^4.0.5"
"styled-components": "2.0.0"
},

@@ -35,4 +36,5 @@ "devDependencies": {

"babel-jest": "^20.0.3",
"babel-loader": "^7.0.0",
"babel-loader": "^7.1.0",
"babel-preset-env": "^1.5.1",
"babel-preset-flow": "^6.23.0",
"babel-preset-react": "^6.24.1",

@@ -43,4 +45,6 @@ "babel-preset-stage-0": "^6.24.1",

"jest-cli": "^20.0.4",
"jest-emotion-react": "^0.0.2",
"jest-glamor-react": "^1.4.0",
"npm-run-all": "^4.0.2",
"prettier-eslint-cli": "^4.0.3",
"pretty-bytes-cli": "^2.0.0",

@@ -50,5 +54,5 @@ "react": "^15.5.4",

"react-dom": "^15.5.4",
"react-test-renderer": "^15.5.4",
"react-test-renderer": "^15.6.1",
"rimraf": "^2.6.1",
"rollup": "^0.41.6",
"rollup": "^0.43.0",
"rollup-plugin-babel": "^2.7.1",

@@ -55,0 +59,0 @@ "rollup-plugin-buble": "^0.15.0",

@@ -1,5 +0,12 @@

# emotion
<h1 align="center" style="color: #343a40">
<img src="https://cdn.rawgit.com/tkh44/emotion/master/emotion.png" alt="emotion" width="200">
<br>
emotion
<br>
</h1>
<p align="center" style="font-size: 1.2rem;">high performance js for your css</p>
## 👩‍🎤 Glam + React
[![npm version](https://badge.fury.io/js/emotion.svg)](https://badge.fury.io/js/emotion)

@@ -16,3 +23,3 @@ [![Build Status](https://travis-ci.org/tkh44/emotion.svg?branch=master)](https://travis-ci.org/tkh44/emotion)

```bash
npm install -S emotion glam
npm install -S emotion
```

@@ -25,4 +32,3 @@

"plugins": [
"emotion/babel",
"glam/babel"
"emotion/babel"
]

@@ -112,17 +118,1 @@ }

### css prop
When using the emotion babel plugin, any `css` prop is converted to a class name via glam and appended to any existing class names.
**Similar to importing React when using jsx, `import css from 'glam'` must be at the top of your source files.**
```jsx harmony
const Name = ({ color, name }) => <h1 css={`color: ${color};`}>{name}</h1>
// is converted to
const Name = ({ color, name }) => <h1 className={css`color: ${color};`}>{name}</h1>
```

@@ -1,112 +0,43 @@

module.exports = function (babel) {
const { types: t } = babel
import { parseKeyframes } from './parser'
import { inline, keyframes } from './inline'
import findAndReplaceAttrs from './attrs'
function createClassNameAttr (expression) {
return t.jSXAttribute(
t.jSXIdentifier('className'),
t.JSXExpressionContainer(expression)
)
}
function parseDynamicValues (rules, t) {
return rules.map(rule => {
const re = /xxx(\S)xxx/gm
let varMatch
let matches = []
while ((varMatch = re.exec(rule)) !== null) {
matches.push({
value: varMatch[0],
p1: varMatch[1],
index: varMatch.index
})
}
function createCssTemplateExpression (templateLiteral) {
return t.taggedTemplateExpression(t.identifier('css'), templateLiteral)
}
function findAndReplaceAttrs (path) {
let quasis = path.node.quasi.quasis
let stubs = path.node.quasi.expressions
let didFindAtLeastOneMatch = false
let [nextQuasis, nextStubs] = quasis.reduce(
(accum, quasi, i) => {
const str = quasi.value.cooked
const regex = /attr\(([\S]+)(?:\s*(em|ex|px|rem|vw|vh|vmin|vmax|mm|cm|in|pt|pc|%)?)(?:,\s*([\S^)]+))?\)/gm
let attrMatch
let matches = []
while ((attrMatch = regex.exec(str)) !== null) {
didFindAtLeastOneMatch = true
matches.push({
value: attrMatch[0],
propName: attrMatch[1],
valueType: attrMatch[2],
defaultValue: attrMatch[3],
index: attrMatch.index
})
let cursor = 0
const [quasis, expressions] = matches.reduce(
(accum, { value, p1, index }, i) => {
const [quasis, expressions] = accum
const preMatch = rule.substring(cursor, index)
cursor = cursor + preMatch.length + value.length
if (preMatch) {
quasis.push(t.templateElement({ raw: preMatch, cooked: preMatch }))
}
let cursor = 0
for (let j = 0; j < matches.length; ++j) {
const match = matches[j]
const value = match.value
const propName = match.propName
const valueType = match.valueType
const defaultValue = match.defaultValue
const index = match.index
const preAttr = `${str.slice(cursor, index)}`
cursor = index + value.length
const postAttr = `${str.slice(cursor)}`
expressions.push(t.identifier(`x${p1}`))
if (preAttr) {
accum[0].push(
t.templateElement({ raw: preAttr, cooked: preAttr }, false)
)
}
if (i === matches.length - 1 && cursor <= rule.length) {
const postMatch = rule.substring(cursor)
if (postAttr && j === matches.length - 1) {
accum[0].push(
t.templateElement(
{ raw: postAttr, cooked: postAttr },
i === quasis.length - 1
)
quasis.push(
t.templateElement(
{
raw: postMatch,
cooked: postMatch
},
true
)
}
let createMemberExpression = () =>
t.memberExpression(t.identifier('props'), t.identifier(propName))
let returnValue = createMemberExpression()
if (valueType) {
returnValue = t.binaryExpression(
'+',
createMemberExpression(),
t.stringLiteral(valueType)
)
}
if (defaultValue) {
returnValue = t.conditionalExpression(
createMemberExpression(),
createMemberExpression(),
t.parenthesizedExpression(
t.binaryExpression(
'+',
t.stringLiteral(defaultValue),
t.stringLiteral(valueType || '')
)
)
)
}
const body = t.blockStatement([t.returnStatement(returnValue)])
const expr = t.functionExpression(
t.identifier(
`get${propName.charAt(0).toUpperCase() + propName.slice(1)}`
),
[t.identifier('props')],
body
)
accum[1].push(expr)
}
if (matches.length === 0) {
accum[0].push(quasi)
if (stubs[i]) {
accum[1].push(stubs[i])
}
} else if (stubs[i]) {
accum[1].push(stubs[i])
}
return accum

@@ -117,124 +48,68 @@ },

if (didFindAtLeastOneMatch) {
return t.templateLiteral(nextQuasis, nextStubs)
if (!matches.length) {
return t.templateLiteral(
[t.templateElement({ raw: rule, cooked: rule }, true)],
[]
)
}
return path.node.quasi
}
return t.templateLiteral(quasis, expressions)
})
}
export default function (babel) {
const { types: t } = babel
return {
name: 'emotion-for-glam', // not required
name: 'emotion', // not required
inherits: require('babel-plugin-syntax-jsx'),
visitor: {
CallExpression (path) {
// styled("h1", ["css-8xpzga", [fontSize], function inlineCss(x0) {
// return [`.css-8xpzga { font-size: ${x0}px; }`];
// }]);
// ->
// styled('h1', [css-12, [color], function inlineCss(x0...){}, ...])
if (path.node.callee.name === 'css') {
const parentPath = path.parentPath
if (
parentPath.isCallExpression() &&
parentPath.node.callee &&
parentPath.node.callee.name === 'styled'
) {
path.replaceWithMultiple(t.arrayExpression(path.node.arguments))
}
}
},
JSXOpeningElement (path, state) {
let cssPath
let classNamesPath
TaggedTemplateExpression (path) {
// in:
// styled.h1`color:${color};`
//
// out:
// styled('h1', "css-r1aqtk", [colorVar, heightVar], function inlineCss(x0, x1) {
// return [`.css-r1aqtk {
// margin: 12px;
// color: ${x0};
// height: ${x1}; }`];
// });
path.get('attributes').forEach(openElPath => {
if (t.isJSXSpreadAttribute(openElPath.node)) {
return
}
const parent = path.findParent(p => p.isVariableDeclarator())
const identifierName = parent && t.isIdentifier(parent.node.id)
? parent.node.id.name
: ''
const attrPath = openElPath.get('name')
const name = attrPath.node.name
function buildCallExpression (identifier, tag, path) {
const built = findAndReplaceAttrs(path, t)
if (name === 'css') {
cssPath = attrPath
}
let { hash, rules, name } = inline(built, identifierName, 'css')
if (name === 'className') {
classNamesPath = attrPath
// hash will be '0' when no styles are passed so we can just return the original tag
if (hash === '0') {
return tag
}
})
if (!cssPath) return
let arrayValues = parseDynamicValues(rules, t)
let cssPropValue = cssPath.container && cssPath.container.value
let classNamesValue =
classNamesPath &&
classNamesPath.container &&
classNamesPath.container.value
if (t.isJSXExpressionContainer(cssPropValue)) {
cssPropValue = cssPropValue.expression
}
let cssTemplateExpression
if (t.isTemplateLiteral(cssPropValue)) {
cssTemplateExpression = createCssTemplateExpression(cssPropValue)
} else if (t.isStringLiteral(cssPropValue)) {
cssTemplateExpression = createCssTemplateExpression(
t.templateLiteral(
[
t.templateElement({
raw: cssPropValue.value,
cooked: cssPropValue.value
})
],
[]
)
const inlineContentExpr = t.functionExpression(
t.identifier('createEmotionStyledRules'),
built.expressions.map((x, i) => t.identifier(`x${i}`)),
t.blockStatement([
t.returnStatement(t.arrayExpression(arrayValues))
])
)
} else {
throw path.buildCodeFrameError(
`${cssPropValue.value} is not a string or template literal`
)
}
const args = [
tag,
t.stringLiteral(`${name}-${hash}`),
t.arrayExpression(built.expressions),
inlineContentExpr
]
if (!classNamesValue) {
cssPath.parentPath.replaceWith(
createClassNameAttr(cssTemplateExpression)
)
return
return t.callExpression(identifier, args)
}
cssPath.parentPath.remove()
if (t.isJSXExpressionContainer(classNamesValue)) {
classNamesPath.parentPath.replaceWith(
createClassNameAttr(
t.binaryExpression(
'+',
t.binaryExpression(
'+',
classNamesValue.expression,
t.stringLiteral(' ')
),
cssTemplateExpression
)
)
)
} else {
classNamesPath.parentPath.replaceWith(
createClassNameAttr(
t.binaryExpression(
'+',
t.binaryExpression(
'+',
t.stringLiteral(classNamesValue.value || ''),
t.stringLiteral(' ')
),
cssTemplateExpression
)
)
)
}
},
TaggedTemplateExpression (path) {
if (
// styled.h1`color:${color};` -> styled('h1', css`color:${color};`)
// styled.h1`color:${color};`
t.isMemberExpression(path.node.tag) &&

@@ -244,12 +119,11 @@ path.node.tag.object.name === 'styled' &&

) {
const built = findAndReplaceAttrs(path)
path.replaceWith(
t.callExpression(path.node.tag.object, [
buildCallExpression(
path.node.tag.object,
t.stringLiteral(path.node.tag.property.name),
t.taggedTemplateExpression(t.identifier('css'), built)
])
path
)
)
} else if (
// styled('h1')`color:${color};` -> styled('h1', css`color:${color};`)
// styled('h1')`color:${color};`
t.isCallExpression(path.node.tag) &&

@@ -259,9 +133,88 @@ path.node.tag.callee.name === 'styled' &&

) {
const built = findAndReplaceAttrs(path)
path.replaceWith(
t.callExpression(path.node.tag.callee, [
buildCallExpression(
path.node.tag.callee,
path.node.tag.arguments[0],
t.taggedTemplateExpression(t.identifier('css'), built)
path
)
)
} else if (
t.isIdentifier(path.node.tag) &&
path.node.tag.name === 'fragment'
) {
const { hash, name, rules } = inline(
path.node.quasi,
identifierName,
'frag'
)
path.replaceWith(
t.callExpression(t.identifier('fragment'), [
t.stringLiteral(`${name}-${hash}`),
t.arrayExpression(path.node.quasi.expressions),
t.functionExpression(
t.identifier('createEmotionFragment'),
path.node.quasi.expressions.map((x, i) =>
t.identifier(`x${i}`)
),
t.blockStatement([
t.returnStatement(
t.arrayExpression(parseDynamicValues(rules, t))
)
])
)
])
)
} else if (
t.isIdentifier(path.node.tag) &&
path.node.tag.name === 'css'
) {
const { hash, name, rules } = inline(
path.node.quasi,
identifierName,
'css'
)
path.replaceWith(
t.callExpression(t.identifier('css'), [
t.stringLiteral(`${name}-${hash}`),
t.arrayExpression(path.node.quasi.expressions),
t.functionExpression(
t.identifier('createEmotionRules'),
path.node.quasi.expressions.map((x, i) =>
t.identifier(`x${i}`)
),
t.blockStatement([
t.returnStatement(
t.arrayExpression(parseDynamicValues(rules, t))
)
])
)
])
)
} else if (
t.isIdentifier(path.node.tag) &&
path.node.tag.name === 'keyframes'
) {
const { hash, name, rules } = keyframes(
path.node.quasi,
identifierName,
'animation'
)
path.replaceWith(
t.callExpression(t.identifier('keyframes'), [
t.stringLiteral(`${name}-${hash}`),
t.arrayExpression(path.node.quasi.expressions),
t.functionExpression(
t.identifier('createEmotionKeyframe'),
path.node.quasi.expressions.map((x, i) =>
t.identifier(`x${i}`)
),
t.blockStatement([
t.returnStatement(
t.arrayExpression(rules.map(r => t.stringLiteral(r)))
)
])
)
])
)
}

@@ -268,0 +221,0 @@ }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc