Skip to content

Commit

Permalink
Add plugins options
Browse files Browse the repository at this point in the history
  • Loading branch information
giuseppeg committed May 28, 2017
1 parent 9a5476d commit 8ac17dd
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 22 deletions.
43 changes: 42 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ Styles can be preprocessed via plugins.
Plugins are regular JavaScript modules that export a simple function with the following signature:

```js
(css: string) => string
(css: string, settings: Object) => string
```

Basically they accept a CSS string in input, optionally modify it and finally return it.
Expand All @@ -147,6 +147,47 @@ Plugins are applied in definition order left to right before styles are scoped.

N.B. when applying the plugins styled-jsx replaces template literals expressions with placeholders e.g. `%%styledjsxexpression_ExprNumber%%` because otherwise CSS parsers would get invalid CSS.

#### Plugin options and settings

Users can set plugin options by registering a plugin as an array that contains
the plugin path and an options object.

```json
{
"plugins": [
[
"styled-jsx/babel",
{
"plugins": [
["my-styled-jsx-plugin-package", { "exampleOption": true }]
],
"sourceMaps": true
}
]
]
}
```

Each plugin receives a `settings` object as second argument which contains
the babel and user options:

```js
export default (css, settings) => { /* ... */ }
```

The `settings` object has the following shape:

```js
{
sourceMaps: true,

// user options
options: {
exampleOption: true
}
}
```

### Targeting The Root

Notice that the parent `<div>` above also gets a `data-jsx` attribute. We do this so that
Expand Down
8 changes: 3 additions & 5 deletions src/_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ export const addSourceMaps = (code, generator, filename) =>
`/*@ sourceURL=${filename} */`
].join('\n')

export const combinePlugins = plugins => {
export const combinePlugins = (plugins, opts) => {
if (!plugins) {
return css => css
}
Expand All @@ -231,14 +231,12 @@ export const combinePlugins = plugins => {
)
}

const env = typeof window === 'undefined' ? 'compile' : 'runtime'

return plugins
.map((plugin, i) => {
let options = {}
if (Array.isArray(plugin)) {
plugin = plugin[0]
options = plugin[1] || {}
plugin = plugin[0]
}

// eslint-disable-next-line import/no-dynamic-require
Expand All @@ -256,7 +254,7 @@ export const combinePlugins = plugins => {
return {
plugin: p,
settings: {
env,
...opts,
options
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/babel-external.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ const callVisitor = (visitor, path, state) => {
const { opts } = file
visitor(path, {
validate: opts.validate,
sourceMaps: opts.sourceMaps,
sourceMaps: state.opts.sourceMaps || opts.sourceMaps,
sourceFileName: opts.sourceFileName,
file,
plugins
Expand Down
10 changes: 7 additions & 3 deletions src/babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const callExternalVisitor = (visitor, path, state) => {
const { opts } = file
visitor(path, {
validate: true,
sourceMaps: opts.sourceMaps,
sourceMaps: state.opts.sourceMaps || opts.sourceMaps,
sourceFileName: opts.sourceFileName,
file,
plugins
Expand Down Expand Up @@ -295,7 +295,9 @@ export default function({ types: t }) {
// We replace styles with the function call
const [id, css, loc] = state.styles.shift()

const useSourceMaps = Boolean(state.file.opts.sourceMaps)
const useSourceMaps = Boolean(
state.opts.sourceMaps || state.file.opts.sourceMaps
)
let transformedCss

if (useSourceMaps) {
Expand Down Expand Up @@ -338,7 +340,9 @@ export default function({ types: t }) {
state.file.hasJSXStyle = false
state.imports = []
if (!plugins) {
plugins = combinePlugins(state.opts.plugins)
plugins = combinePlugins(state.opts.plugins, {
sourceMaps: state.opts.sourceMaps || state.file.opts.sourceMaps
})
}
},
exit({ node, scope }, state) {
Expand Down
18 changes: 18 additions & 0 deletions test/__snapshots__/index.js.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`generates source maps (babel options) 1`] = `
"import _JSXStyle from 'styled-jsx/style';
export default (() => <div data-jsx={188072295}>
<p data-jsx={188072295}>test</p>
<p data-jsx={188072295}>woot</p>
<_JSXStyle styleId={188072295} css={\\"p[data-jsx=\\\\\\"188072295\\\\\\"]{color:red}\\\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiJzb3VyY2UtbWFwcy5qcyIsInNvdXJjZXNDb250ZW50IjpbXX0= */\\\\n/*@ sourceURL=source-maps.js */\\"} />
</div>);"
`;

exports[`generates source maps (plugin options) 1`] = `
"import _JSXStyle from 'styled-jsx/style';
export default (() => <div data-jsx={188072295}>
<p data-jsx={188072295}>test</p>
<p data-jsx={188072295}>woot</p>
<_JSXStyle styleId={188072295} css={\\"p[data-jsx=\\\\\\"188072295\\\\\\"]{color:red}\\\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiJzb3VyY2UtbWFwcy5qcyIsInNvdXJjZXNDb250ZW50IjpbXX0= */\\\\n/*@ sourceURL=source-maps.js */\\"} />
</div>);"
`;

exports[`generates source maps 1`] = `
"import _JSXStyle from 'styled-jsx/style';
export default (() => <div data-jsx={188072295}>
Expand Down
13 changes: 13 additions & 0 deletions test/__snapshots__/plugins.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`applies plugins 1`] = `
"import _JSXStyle from 'styled-jsx/style';
import styles from './styles';
const color = 'red';
export default (() => <div data-jsx={4216192053} data-jsx-ext={styles.__scopedHash}>
<p data-jsx={4216192053} data-jsx-ext={styles.__scopedHash}>test</p>
<_JSXStyle styleId={4216192053} css={\`span[data-jsx=\\"4216192053\\"].\${color}[data-jsx=\\"4216192053\\"]{color:\${otherColor}}\`} />
<_JSXStyle styleId={styles.__scopedHash} css={styles.__scoped} />
</div>);"
`;
1 change: 1 addition & 0 deletions test/fixtures/plugins/options.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default (css, settings) => settings.options.test
9 changes: 8 additions & 1 deletion test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,20 @@ test('works with global styles', async t => {
t.snapshot(code)
})

test('generates source maps', async t => {
test('generates source maps (babel options)', async t => {
const { code } = await transform('./fixtures/source-maps.js', {
sourceMaps: true
})
t.snapshot(code)
})

test('generates source maps (plugin options)', async t => {
const { code } = await _transform('./fixtures/source-maps.js', {
plugins: [[plugin, { sourceMaps: true }]]
})
t.snapshot(code)
})

test('mixed global and scoped', async t => {
const { code } = await transform('./fixtures/mixed-global-scoped.js')
t.snapshot(code)
Expand Down
30 changes: 19 additions & 11 deletions test/plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,21 @@ import test from 'ava'

// Ours
import babelPlugin from '../src/babel'
import {combinePlugins} from '../src/_utils'
import { combinePlugins } from '../src/_utils'
import _transform from './_transform'
import read from './_read'
import testPlugin1 from './fixtures/plugins/plugin'
import testPlugin2 from './fixtures/plugins/another-plugin'

const transform = (file, opts = {}) => (
const transform = (file, opts = {}) =>
_transform(file, {
plugins: [
[
babelPlugin,
{plugins: [require.resolve('./fixtures/plugins/another-plugin')]}
{ plugins: [require.resolve('./fixtures/plugins/another-plugin')] }
]
],
...opts
})
)

test('combinePlugins returns an identity function when plugins is undefined', t => {
const test = 'test'
Expand Down Expand Up @@ -49,13 +47,24 @@ test('combinePlugins throws if loaded plugins are not functions', t => {
})

test('combinePlugins works with a single plugin', t => {
const plugins = combinePlugins([
require.resolve('./fixtures/plugins/plugin')
])
const plugins = combinePlugins([require.resolve('./fixtures/plugins/plugin')])

t.is(testPlugin1('test'), plugins('test'))
})

test('combinePlugins works with options', t => {
const expectedOption = 'my-test'
const plugins = combinePlugins([
[
require.resolve('./fixtures/plugins/options'),
{
test: expectedOption
}
]
])
t.is(plugins(''), expectedOption)
})

test('combinePlugins applies plugins left to right', t => {
const plugins = combinePlugins([
require.resolve('./fixtures/plugins/plugin'),
Expand All @@ -66,7 +75,6 @@ test('combinePlugins applies plugins left to right', t => {
})

test('applies plugins', async t => {
const {code} = await transform('./fixtures/with-plugins.js')
const out = await read('./fixtures/with-plugins.out.js')
t.is(code, out.trim())
const { code } = await transform('./fixtures/with-plugins.js')
t.snapshot(code)
})

0 comments on commit 8ac17dd

Please sign in to comment.