diff --git a/README.md b/README.md index a4b730c6d..ef22a8cb3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # emotion -#### `css` prop for all +## 👩‍🎤 Glam + React [![npm version](https://badge.fury.io/js/emotion.svg)](https://badge.fury.io/js/emotion) [![Build Status](https://travis-ci.org/tkh44/emotion.svg?branch=master)](https://travis-ci.org/tkh44/emotion) @@ -8,23 +8,14 @@ - [Install](#install) -- [glam](#emotionglam) -- [glamor](#emotionglamor) -- [cxs](#emotioncxs) +- [Example Project](https://github.com/tkh44/emotion/tree/master/examples/glam) ## Install ```bash -npm install -S emotion +npm install -S emotion glam ``` -## `emotion/glam` - -[Example Project](https://github.com/tkh44/emotion/tree/master/examples/glam) - -```bash -npm install -S glam -``` **.babelrc** ```json @@ -36,72 +27,62 @@ npm install -S glam } ``` -```jsx harmony -const Name = ({ color, name }) =>

{name}

-``` - -is converted to +### glam -```jsx harmony -const Name = ({ color, name }) =>

{name}

-``` +```jsx +import glam from 'emotion' +const H1 = glam('h1')` + color: 'blue'; + font-size: 48px; + transform: scale(${props => props.scale}); +` -**Similar to importing React when using jsx, `import css from 'glam'` must be at the top of your source files.** +// can be used as any other normal component -## `emotion/glamor` +function Greeting ({ name }) { + return

Hello {name}

// blue, 48px, and scaled 2x text +} -```bash -npm install -S glamor -``` +/* +

+ Hello user +

+*/ -**.babelrc** -```json -{ - "plugins": [ - "emotion/glamor", - ] -} -``` +// You can also pass components in -```jsx harmony -const Name = ({ color, name }) =>

{name}

-``` +const H2 = glam(H1)` + font-size: ${fontSize * 2/3}px; + color: 'red'; +` -is converted to +function Greeting ({ name }) { + return

Hello {name}

// red, 32px, and scaled 2x text +} -```jsx harmony -const Name = ({ color, name }) =>

{name}

+/* +

` + Hello user +

+*/ +// results ``` -**Similar to importing React when using jsx, `import {css} from 'glamor'` must be at the top of your source files.** +### css prop -## `emotion/cxs` +When using the emotion babel plugin, any `css` prop is converted to a class name via glam and appended to any existing class names. -```bash -npm install -S cxs -``` - -**.babelrc** -```json -{ - "plugins": [ - "emotion/cxs", - ] -} -``` ```jsx harmony -const Name = ({ color, name }) =>

{name}

-``` +const Name = ({ color, name }) =>

{name}

-is converted to +// is converted to -```jsx harmony -const Name = ({ color, name }) =>

{name}

+const Name = ({ color, name }) =>

{name}

``` - - -**Similar to importing React when using jsx, `import cxs from 'cxs'` must be at the top of your source files.** - diff --git a/cxs.js b/cxs.js deleted file mode 100644 index 5e9e73237..000000000 --- a/cxs.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./src/cxs/babel') diff --git a/glamor.js b/glamor.js deleted file mode 100644 index d2cce17a5..000000000 --- a/glamor.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./src/glamor/babel') diff --git a/package.json b/package.json index a5dd4faff..4414ecb6e 100644 --- a/package.json +++ b/package.json @@ -1,38 +1,57 @@ { "name": "emotion", "version": "0.0.6", - "description": "css prop for all", + "description": "👩‍🎤 Glam + React", + "jsnext:main": "dist/emotion.es.js", + "module": "dist/emotion.es.js", + "main": "dist/glam.js", + "umd:main": "dist/emotion.umd.js", "files": [ "src", "glam.js" ], "scripts": { + "build": "npm-run-all clean -p rollup -p minify:* -s size", + "clean": "rimraf dist", "test": "standard src test && jest --coverage", - "test:watch": "jest --watch --coverage", - "release": "npm run test && npm version patch && npm publish && git push --tags" + "test:watch": "jest --watch", + "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" }, "dependencies": { - "babel-plugin-syntax-jsx": "^6.18.0" + "babel-plugin-syntax-jsx": "^6.18.0", + "glam": "^4.0.3" }, "devDependencies": { "babel-cli": "^6.24.1", "babel-core": "^6.24.1", "babel-eslint": "^7.2.3", - "babel-jest": "^19.0.0", + "babel-jest": "^20.0.3", "babel-loader": "^7.0.0", - "babel-preset-env": "^1.4.0", + "babel-preset-env": "^1.5.1", "babel-preset-react": "^6.24.1", "babel-preset-stage-0": "^6.24.1", - "cxs": "^3.0.4", - "glam": "^4.0.3", - "glamor": "^2.20.25", - "jest": "^20.0.1", - "jest-glamor-react": "^1.3.0", + "gzip-size-cli": "^2.0.0", + "jest": "^20.0.4", + "jest-cli": "^20.0.4", + "jest-glamor-react": "^1.4.0", + "npm-run-all": "^4.0.2", + "pretty-bytes-cli": "^2.0.0", "react": "^15.5.4", "react-addons-test-utils": "^15.5.1", "react-dom": "^15.5.4", "react-test-renderer": "^15.5.4", - "standard": "^10.0.2" + "rimraf": "^2.6.1", + "rollup": "^0.41.6", + "rollup-plugin-babel": "^2.7.1", + "rollup-plugin-commonjs": "^8.0.2", + "rollup-plugin-node-resolve": "^3.0.0", + "standard": "^10.0.2", + "strip-json-comments-cli": "^1.0.1", + "uglify-js": "2.8.23" }, "author": "Kye Hohenberger", "homepage": "https://github.com/tkh44/emotion#readme", @@ -63,6 +82,5 @@ }, "bugs": { "url": "https://github.com/tkh44/emotion/issues" - }, - "main": "glam.js" + } } diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 000000000..20311dd04 --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,34 @@ +import fs from 'fs' +import babel from 'rollup-plugin-babel' +import resolve from 'rollup-plugin-node-resolve' +import commonjs from 'rollup-plugin-commonjs' + +const pkg = JSON.parse(fs.readFileSync('./package.json')) + +export default { + entry: 'src/react.js', + external: ['react', 'prop-types', 'glam'], + exports: 'named', + globals: { react: 'React', 'prop-types': 'PropTypes', glam: 'glam' }, + useStrict: false, + sourceMap: true, + plugins: [ + babel({ + exclude: 'node_modules/**' + }), + resolve({ + jsnext: false, + main: true, + browser: true + }), + commonjs({ + ignoreGlobal: true, + include: 'node_modules/**' + }) + ], + targets: [ + {dest: pkg.main, format: 'cjs'}, + {dest: pkg.module, format: 'es'}, + {dest: pkg['umd:main'], format: 'umd', moduleName: pkg.name} + ] +} diff --git a/src/glam/__tests__/.babelrc b/src/__tests__/.babelrc similarity index 100% rename from src/glam/__tests__/.babelrc rename to src/__tests__/.babelrc diff --git a/src/__tests__/__snapshots__/babel.js.snap b/src/__tests__/__snapshots__/babel.js.snap new file mode 100644 index 000000000..c7a78296b --- /dev/null +++ b/src/__tests__/__snapshots__/babel.js.snap @@ -0,0 +1,60 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`emotion/glam babel css prop StringLiteral css prop value 1`] = `"
;"`; + +exports[`emotion/glam babel css prop basic 1`] = `"
;"`; + +exports[`emotion/glam babel css prop className as expression 1`] = `"
;"`; + +exports[`emotion/glam babel css prop className as expression string 1`] = `"
;"`; + +exports[`emotion/glam babel css prop css empty 1`] = `"
;"`; + +exports[`emotion/glam babel css prop emptyClassName 1`] = `"
;"`; + +exports[`emotion/glam babel css prop no css attr 1`] = `"
;"`; + +exports[`emotion/glam babel css prop noClassName 1`] = `"
;"`; + +exports[`emotion/glam real basic 1`] = ` +

+ hello world +

+`; + +exports[`emotion/glam real kitchen sink 1`] = ` +
+

+ BOOM +

+

+ Hello +

+

+ World +

+

+ hello world +

+
+`; + +exports[`emotion/glam real string expression 1`] = ` +

+ hello world +

+`; diff --git a/src/__tests__/__snapshots__/react.js.snap b/src/__tests__/__snapshots__/react.js.snap new file mode 100644 index 000000000..4a200f80c --- /dev/null +++ b/src/__tests__/__snapshots__/react.js.snap @@ -0,0 +1,38 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`glam react babel glam component basic 1`] = `"glam(\\"h1\\", ['css-8xpzga', [fontSize]]);"`; + +exports[`glam react babel glam component function call 1`] = `"glam(MyComponent, ['css-8xpzga', [fontSize]]);"`; + +exports[`glam react basic render 1`] = ` +

+ hello world +

+`; + +exports[`glam react call expression 1`] = ` +

+ hello world +

+`; + +exports[`glam react composition 1`] = ` +

+ hello world +

+`; + +exports[`glam react function in expression 1`] = ` +

+ hello world +

+`; diff --git a/src/glam/__tests__/index.js b/src/__tests__/babel.js similarity index 97% rename from src/glam/__tests__/index.js rename to src/__tests__/babel.js index a5fc858fe..322dd99da 100644 --- a/src/glam/__tests__/index.js +++ b/src/__tests__/babel.js @@ -1,4 +1,4 @@ -/* eslint-disable jsx-quotes,no-useless-escape */ +/* eslint-disable jsx-quotes,no-useless-escape,no-template-curly-in-string */ /* eslint-env jest */ import React from 'react' import renderer from 'react-test-renderer' @@ -8,7 +8,7 @@ import css, {fragment} from 'glam' const babel = require('babel-core') describe('emotion/glam', () => { - describe('babel', () => { + describe('babel css prop', () => { test('basic', () => { const basic = '(
)' const {code} = babel.transform(basic, {plugins: [plugin, 'glam/babel']}) diff --git a/src/glam/__tests__/index.js.css b/src/__tests__/babel.js.css similarity index 100% rename from src/glam/__tests__/index.js.css rename to src/__tests__/babel.js.css diff --git a/src/__tests__/react.js b/src/__tests__/react.js new file mode 100644 index 000000000..1915e4d97 --- /dev/null +++ b/src/__tests__/react.js @@ -0,0 +1,97 @@ +/* eslint-disable jsx-quotes,no-useless-escape,no-template-curly-in-string */ +/* eslint-env jest */ +import React from 'react' +import renderer from 'react-test-renderer' +import css, {fragment} from 'glam' +import glam from '../react' +import plugin from '../babel' + +const babel = require('babel-core') + +describe('glam react', () => { + describe('babel glam component', () => { + test('basic', () => { + const basic = 'glam.h1\`font-size: \$\{fontSize\}px;\`' + const {code} = babel.transform(basic, {plugins: [plugin, 'glam/babel']}) + expect(code).toMatchSnapshot() + }) + + test('function call', () => { + const basic = 'glam(MyComponent)\`font-size: \$\{fontSize\}px;\`' + const {code} = babel.transform(basic, {plugins: [plugin, 'glam/babel']}) + expect(code).toMatchSnapshot() + }) + }) + + test('basic render', () => { + const fontSize = 20 + const H1 = glam.h1` + font-size: ${fontSize}px; + ` + + const tree = renderer + .create( +

+ hello world +

+ ) + .toJSON() + + expect(tree).toMatchSnapshot() + }) + + test('call expression', () => { + const fontSize = 20 + const H1 = glam('h1')` + font-size: ${fontSize}px; + ` + + const tree = renderer + .create( +

+ hello world +

+ ) + .toJSON() + + expect(tree).toMatchSnapshot() + }) + + test('composition', () => { + const fontSize = 20 + const H1 = glam('h1')` + font-size: ${fontSize}px; + ` + + const H2 = glam(H1)`font-size: ${fontSize * 2 / 3}` + + const tree = renderer + .create( +

+ hello world +

+ ) + .toJSON() + + expect(tree).toMatchSnapshot() + }) + + test('function in expression', () => { + const fontSize = 20 + const H1 = glam('h1')` + font-size: ${fontSize}px; + ` + + const H2 = glam(H1)`font-size: ${({ scale }) => fontSize * scale}` + + const tree = renderer + .create( +

+ hello world +

+ ) + .toJSON() + + expect(tree).toMatchSnapshot() + }) +}) diff --git a/src/__tests__/react.js.css b/src/__tests__/react.js.css new file mode 100644 index 000000000..50c474777 --- /dev/null +++ b/src/__tests__/react.js.css @@ -0,0 +1,3 @@ +/* do not edit this file */ +.css-13wdnau { font-size: var(--css-13wdnau-0)px; } +.css-vxb7tq { font-size: var(--css-vxb7tq-0) } \ No newline at end of file diff --git a/src/glam/babel.js b/src/babel.js similarity index 70% rename from src/glam/babel.js rename to src/babel.js index 268b0c4f9..d1d8d1171 100644 --- a/src/glam/babel.js +++ b/src/babel.js @@ -16,6 +16,18 @@ module.exports = function (babel) { name: 'emotion-for-glam', // not required inherits: require('babel-plugin-syntax-jsx'), visitor: { + CallExpression (path) { + if (path.node.callee.name === 'css') { + const parentPath = path.parentPath + if ( + parentPath.isCallExpression() && + parentPath.node.callee && + parentPath.node.callee.name === 'glam' + ) { + path.replaceWithMultiple(t.arrayExpression(path.node.arguments)) + } + } + }, JSXOpeningElement (path, state) { let cssPath let classNamesPath @@ -41,8 +53,6 @@ module.exports = function (babel) { classNamesPath.container && classNamesPath.container.value - // if (!cssPropValue) return - if (t.isJSXExpressionContainer(cssPropValue)) { cssPropValue = cssPropValue.expression } @@ -106,9 +116,29 @@ module.exports = function (babel) { ) } }, - JSXAttribute (path, state) { - if (path.node.name.name === 'css') { - console.log('whatup', path.node.value) + TaggedTemplateExpression (path) { + if ( + t.isMemberExpression(path.node.tag) && + path.node.tag.object.name === 'glam' && + t.isTemplateLiteral(path.node.quasi) + ) { + path.replaceWith( + t.callExpression(t.identifier(path.node.tag.object.name), [ + t.stringLiteral(path.node.tag.property.name), + t.taggedTemplateExpression(t.identifier('css'), path.node.quasi) + ]) + ) + } else if ( + t.isCallExpression(path.node.tag) && + path.node.tag.callee.name === 'glam' && + t.isTemplateLiteral(path.node.quasi) + ) { + path.replaceWith( + t.callExpression(t.identifier(path.node.tag.callee.name), [ + path.node.tag.arguments[0], + t.taggedTemplateExpression(t.identifier('css'), path.node.quasi) + ]) + ) } } } diff --git a/src/cxs/__tests__/.babelrc b/src/cxs/__tests__/.babelrc deleted file mode 100644 index 1f68b4d6a..000000000 --- a/src/cxs/__tests__/.babelrc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "presets": [ - "env", - "stage-0", - "react" - ], - "plugins": [ - ["../babel.js"], - ] -} diff --git a/src/cxs/__tests__/__snapshots__/index.js.snap b/src/cxs/__tests__/__snapshots__/index.js.snap deleted file mode 100644 index 0b9d9ef53..000000000 --- a/src/cxs/__tests__/__snapshots__/index.js.snap +++ /dev/null @@ -1,52 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`emotion/cxs babel basic 1`] = `"
;"`; - -exports[`emotion/cxs babel className as expression 1`] = `"
;"`; - -exports[`emotion/cxs babel className as expression string 1`] = `"
;"`; - -exports[`emotion/cxs babel css empty 1`] = `"
;"`; - -exports[`emotion/cxs babel emptyClassName 1`] = `"
;"`; - -exports[`emotion/cxs babel no className 1`] = `"
;"`; - -exports[`emotion/cxs babel no css attr 1`] = `"
;"`; - -exports[`emotion/cxs babel wrong value type 1`] = `"
;"`; - -exports[`emotion/cxs real basic 1`] = ` -

- hello world -

-`; - -exports[`emotion/cxs real kitchen sink 1`] = ` -
-

- BOOM -

-

- Hello -

-

- World -

-

- hello world -

-
-`; diff --git a/src/cxs/__tests__/index.js b/src/cxs/__tests__/index.js deleted file mode 100644 index 3800fac08..000000000 --- a/src/cxs/__tests__/index.js +++ /dev/null @@ -1,106 +0,0 @@ -/* eslint-disable jsx-quotes,no-useless-escape */ -/* eslint-env jest */ -import React from 'react' -import renderer from 'react-test-renderer' -import plugin from '../babel' -import {matcher, serializer} from 'jest-glamor-react' -import cxs from 'cxs' - -expect.addSnapshotSerializer(serializer) -expect.extend(matcher) - -const babel = require('babel-core') - -describe('emotion/cxs', () => { - describe('babel', () => { - test('basic', () => { - const basic = `(
)` - const {code} = babel.transform(basic, {plugins: [plugin]}) - expect(code).toMatchSnapshot() - }) - - test('no css attr', () => { - const basic = '(
)' - const {code} = babel.transform(basic, {plugins: [plugin]}) - expect(code).toMatchSnapshot() - }) - - test('css empty', () => { - const basic = '(
)' - const {code} = babel.transform(basic, {plugins: [plugin]}) - expect(code).toMatchSnapshot() - }) - - test('wrong value type', () => { - const basic = '(
)' - const {code} = babel.transform(basic, {plugins: [plugin]}) - expect(code).toMatchSnapshot() - }) - - test('no className', () => { - const basic = `(
)` - const {code} = babel.transform(basic, {plugins: [plugin]}) - expect(code).toMatchSnapshot() - }) - - test('emptyClassName', () => { - const basic = `(
)` - const {code} = babel.transform(basic, {plugins: [plugin]}) - expect(code).toMatchSnapshot() - }) - - test('className as expression', () => { - const basic = `(
)` - const {code} = babel.transform(basic, {plugins: [plugin]}) - expect(code).toMatchSnapshot() - }) - - test('className as expression string', () => { - const basic = - "(
)" - const {code} = babel.transform(basic, {plugins: [plugin]}) - expect(code).toMatchSnapshot() - }) - }) - - describe('real', () => { - test('basic', (done) => { - const tree = renderer - .create( -

- hello world -

- ) - .toJSON() - - expect(tree).toMatchSnapshotWithGlamor() - setTimeout(done) - }) - - test('kitchen sink', (done) => { - const tree = renderer - .create( -
-

- BOOM -

-

Hello

-

- World -

-

- hello world -

- -
- ) - .toJSON() - - expect(tree).toMatchSnapshotWithGlamor() - setTimeout(done) - }) - }) -}) diff --git a/src/cxs/babel.js b/src/cxs/babel.js deleted file mode 100644 index c75eafde4..000000000 --- a/src/cxs/babel.js +++ /dev/null @@ -1,86 +0,0 @@ -module.exports = function (babel) { - const {types: t} = babel - - function createClassNameAttr (expression) { - return t.jSXAttribute( - t.jSXIdentifier('className'), - t.JSXExpressionContainer(expression) - ) - } - - return { - name: 'emotion-for-cxs', // not required - inherits: require('babel-plugin-syntax-jsx'), - visitor: { - JSXOpeningElement (path, state) { - let cssPath - let classNamesPath - - path.get('attributes').forEach(openElPath => { - const attrPath = openElPath.get('name') - const name = attrPath.node.name - - if (name === 'css') { - cssPath = attrPath - } - - if (name === 'className') { - classNamesPath = attrPath - } - }) - - if (!cssPath) return - - let cssPropValue = cssPath.container && cssPath.container.value - let classNamesValue = - classNamesPath && - classNamesPath.container && - classNamesPath.container.value - - if (t.isJSXExpressionContainer(cssPropValue)) { - cssPropValue = cssPropValue.expression - } - - let cxsCssFunction = t.callExpression(t.identifier('cxs'), [ - cssPropValue - ]) - - if (!classNamesValue) { - cssPath.parentPath.replaceWith(createClassNameAttr(cxsCssFunction)) - return - } - - cssPath.parentPath.remove() - if (t.isJSXExpressionContainer(classNamesValue)) { - classNamesPath.parentPath.replaceWith( - createClassNameAttr( - t.binaryExpression( - '+', - t.binaryExpression( - '+', - classNamesValue.expression, - t.stringLiteral(' ') - ), - cxsCssFunction - ) - ) - ) - } else { - classNamesPath.parentPath.replaceWith( - createClassNameAttr( - t.binaryExpression( - '+', - t.binaryExpression( - '+', - t.stringLiteral(classNamesValue.value || ''), - t.stringLiteral(' ') - ), - cxsCssFunction - ) - ) - ) - } - } - } - } -} diff --git a/src/glam/__tests__/__snapshots__/index.js.snap b/src/glam/__tests__/__snapshots__/index.js.snap deleted file mode 100644 index 0fc06a538..000000000 --- a/src/glam/__tests__/__snapshots__/index.js.snap +++ /dev/null @@ -1,60 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`emotion/glam babel StringLiteral css prop value 1`] = `"
;"`; - -exports[`emotion/glam babel basic 1`] = `"
;"`; - -exports[`emotion/glam babel className as expression 1`] = `"
;"`; - -exports[`emotion/glam babel className as expression string 1`] = `"
;"`; - -exports[`emotion/glam babel css empty 1`] = `"
;"`; - -exports[`emotion/glam babel emptyClassName 1`] = `"
;"`; - -exports[`emotion/glam babel no css attr 1`] = `"
;"`; - -exports[`emotion/glam babel noClassName 1`] = `"
;"`; - -exports[`emotion/glam real basic 1`] = ` -

- hello world -

-`; - -exports[`emotion/glam real kitchen sink 1`] = ` -
-

- BOOM -

-

- Hello -

-

- World -

-

- hello world -

-
-`; - -exports[`emotion/glam real string expression 1`] = ` -

- hello world -

-`; diff --git a/src/glamor/__tests__/.babelrc b/src/glamor/__tests__/.babelrc deleted file mode 100644 index 1f68b4d6a..000000000 --- a/src/glamor/__tests__/.babelrc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "presets": [ - "env", - "stage-0", - "react" - ], - "plugins": [ - ["../babel.js"], - ] -} diff --git a/src/glamor/__tests__/__snapshots__/index.js.snap b/src/glamor/__tests__/__snapshots__/index.js.snap deleted file mode 100644 index 2e03eb77c..000000000 --- a/src/glamor/__tests__/__snapshots__/index.js.snap +++ /dev/null @@ -1,91 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`emotion/glamor babel basic 1`] = `"
;"`; - -exports[`emotion/glamor babel className as expression 1`] = `"
;"`; - -exports[`emotion/glamor babel className as expression string 1`] = `"
;"`; - -exports[`emotion/glamor babel css empty 1`] = `"
;"`; - -exports[`emotion/glamor babel emptyClassName 1`] = `"
;"`; - -exports[`emotion/glamor babel no className 1`] = `"
;"`; - -exports[`emotion/glamor babel no css attr 1`] = `"
;"`; - -exports[`emotion/glamor babel wrong value type 1`] = `"
;"`; - -exports[`emotion/glamor real basic 1`] = ` -.css-1ezp9xe, -[data-css-1ezp9xe] { - color: red; -} - -

- hello world -

-`; - -exports[`emotion/glamor real kitchen sink 1`] = ` -.css-icjsl7, -[data-css-icjsl7] { - color: blue; -} - -.css-gvvg5g, -[data-css-gvvg5g] { - color: gray; -} - -.css-16ywyew, -[data-css-16ywyew] { - border: 1px solid blue; -} - -.css-1cqgl9p, -[data-css-1cqgl9p] { - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; - display: flex; -} - -@media (min-width: 420px) { - .css-198yaui, - [data-css-198yaui] { - font-size: 48px; - } -} - -
-

- BOOM -

-

- Hello -

-

- World -

-

- hello world -

-
-`; diff --git a/src/glamor/__tests__/index.js b/src/glamor/__tests__/index.js deleted file mode 100644 index d750cffb1..000000000 --- a/src/glamor/__tests__/index.js +++ /dev/null @@ -1,104 +0,0 @@ -/* eslint-disable jsx-quotes,no-useless-escape */ -/* eslint-env jest */ -import React from 'react' -import renderer from 'react-test-renderer' -import plugin from '../babel' -import { matcher, serializer } from 'jest-glamor-react' -import { css } from 'glamor' - -expect.addSnapshotSerializer(serializer) -expect.extend(matcher) - -const babel = require('babel-core') - -describe('emotion/glamor', () => { - describe('babel', () => { - test('basic', () => { - const basic = `(
)` - const {code} = babel.transform(basic, {plugins: [plugin]}) - expect(code).toMatchSnapshot() - }) - - test('no css attr', () => { - const basic = '(
)' - const {code} = babel.transform(basic, {plugins: [plugin]}) - expect(code).toMatchSnapshot() - }) - - test('css empty', () => { - const basic = '(
)' - const {code} = babel.transform(basic, {plugins: [plugin]}) - expect(code).toMatchSnapshot() - }) - - test('wrong value type', () => { - const basic = '(
)' - const {code} = babel.transform(basic, {plugins: [plugin]}) - expect(code).toMatchSnapshot() - }) - - test('no className', () => { - const basic = `(
)` - const {code} = babel.transform(basic, {plugins: [plugin]}) - expect(code).toMatchSnapshot() - }) - - test('emptyClassName', () => { - const basic = `(
)` - const {code} = babel.transform(basic, {plugins: [plugin]}) - expect(code).toMatchSnapshot() - }) - - test('className as expression', () => { - const basic = `(
)` - const {code} = babel.transform(basic, {plugins: [plugin]}) - expect(code).toMatchSnapshot() - }) - - test('className as expression string', () => { - const basic = - "(
)" - const {code} = babel.transform(basic, {plugins: [plugin]}) - expect(code).toMatchSnapshot() - }) - }) - - describe('real', () => { - test('basic', () => { - const tree = renderer - .create( -

- hello world -

- ) - .toJSON() - - expect(tree).toMatchSnapshotWithGlamor() - }) - - test('kitchen sink', () => { - const tree = renderer - .create( -
-

- BOOM -

-

Hello

-

- World -

-

- hello world -

- -
- ) - .toJSON() - - expect(tree).toMatchSnapshotWithGlamor() - }) - }) -}) diff --git a/src/glamor/babel.js b/src/glamor/babel.js deleted file mode 100644 index ceaa23b59..000000000 --- a/src/glamor/babel.js +++ /dev/null @@ -1,37 +0,0 @@ -module.exports = function (babel) { - const {types: t} = babel - - return { - name: 'emotion-for-glam', // not required - inherits: require('babel-plugin-syntax-jsx'), - visitor: { - JSXOpeningElement (path, state) { - let cssPath - - path.get('attributes').forEach(openElPath => { - const attrPath = openElPath.get('name') - const name = attrPath.node.name - - if (name === 'css') { - cssPath = attrPath - } - }) - - if (!cssPath) return - - let cssPropValue = cssPath.container && cssPath.container.value - - if (t.isJSXExpressionContainer(cssPropValue)) { - cssPropValue = cssPropValue.expression - } - - let glamorCssFunction = t.callExpression(t.identifier('css'), [ - cssPropValue - ]) - - cssPath.parentPath.insertAfter(t.jSXSpreadAttribute(glamorCssFunction)) - cssPath.parentPath.remove() - } - } - } -} diff --git a/src/react.js b/src/react.js new file mode 100644 index 000000000..6e0c69d36 --- /dev/null +++ b/src/react.js @@ -0,0 +1,20 @@ +import React from 'react' +import css from 'glam' + +const h = React.createElement + +export default function glam (tag, [cls, vars]) { + return class Target extends React.Component { + render () { + const finalClassName = css( + cls, + vars.map(v => (typeof v === 'function' ? v(this.props) : v)) + ) + + return h(tag, { + ...this.props, + className: (this.props.className || '') + ' ' + finalClassName + }) + } + } +}