diff --git a/readme.md b/readme.md
index 48a4bdbc..66ed0965 100644
--- a/readme.md
+++ b/readme.md
@@ -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.
@@ -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 `
` above also gets a `data-jsx` attribute. We do this so that
diff --git a/src/_utils.js b/src/_utils.js
index b0ff4162..556d47cf 100644
--- a/src/_utils.js
+++ b/src/_utils.js
@@ -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
}
@@ -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
@@ -256,7 +254,7 @@ export const combinePlugins = plugins => {
return {
plugin: p,
settings: {
- env,
+ ...opts,
options
}
}
diff --git a/src/babel-external.js b/src/babel-external.js
index 4c4914db..88bc400c 100644
--- a/src/babel-external.js
+++ b/src/babel-external.js
@@ -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
diff --git a/src/babel.js b/src/babel.js
index b0e16598..afc0b951 100644
--- a/src/babel.js
+++ b/src/babel.js
@@ -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
@@ -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) {
@@ -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) {
diff --git a/test/__snapshots__/index.js.snap b/test/__snapshots__/index.js.snap
index ffb119df..bac0e894 100644
--- a/test/__snapshots__/index.js.snap
+++ b/test/__snapshots__/index.js.snap
@@ -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 (() =>
+
test
+
woot
+ <_JSXStyle styleId={188072295} css={\\"p[data-jsx=\\\\\\"188072295\\\\\\"]{color:red}\\\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiJzb3VyY2UtbWFwcy5qcyIsInNvdXJjZXNDb250ZW50IjpbXX0= */\\\\n/*@ sourceURL=source-maps.js */\\"} />
+
);"
+`;
+
+exports[`generates source maps (plugin options) 1`] = `
+"import _JSXStyle from 'styled-jsx/style';
+export default (() =>
+
test
+
woot
+ <_JSXStyle styleId={188072295} css={\\"p[data-jsx=\\\\\\"188072295\\\\\\"]{color:red}\\\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiJzb3VyY2UtbWFwcy5qcyIsInNvdXJjZXNDb250ZW50IjpbXX0= */\\\\n/*@ sourceURL=source-maps.js */\\"} />
+
);"
+`;
+
exports[`generates source maps 1`] = `
"import _JSXStyle from 'styled-jsx/style';
export default (() =>
diff --git a/test/__snapshots__/plugins.js.snap b/test/__snapshots__/plugins.js.snap
new file mode 100644
index 00000000..d71c9954
--- /dev/null
+++ b/test/__snapshots__/plugins.js.snap
@@ -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 (() =>
+
test
+ <_JSXStyle styleId={4216192053} css={\`span[data-jsx=\\"4216192053\\"].\${color}[data-jsx=\\"4216192053\\"]{color:\${otherColor}}\`} />
+ <_JSXStyle styleId={styles.__scopedHash} css={styles.__scoped} />
+
);"
+`;
diff --git a/test/fixtures/plugins/options.js b/test/fixtures/plugins/options.js
new file mode 100644
index 00000000..d0c4376d
--- /dev/null
+++ b/test/fixtures/plugins/options.js
@@ -0,0 +1 @@
+export default (css, settings) => settings.options.test
diff --git a/test/index.js b/test/index.js
index 905a9b77..52668f5c 100644
--- a/test/index.js
+++ b/test/index.js
@@ -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)
diff --git a/test/plugins.js b/test/plugins.js
index fcdbb66e..09e9956e 100644
--- a/test/plugins.js
+++ b/test/plugins.js
@@ -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'
@@ -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'),
@@ -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)
})