Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
283 changes: 283 additions & 0 deletions __tests__/processPlugins.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import _ from 'lodash'
import _postcss from 'postcss'
import tailwind from '../src/index'
import processPlugins from '../src/util/processPlugins'
import createPlugin from '../src/util/createPlugin'

function css(nodes) {
return _postcss.root({ nodes }).toString()
Expand Down Expand Up @@ -1287,3 +1289,284 @@ test('plugins can provide a config but no handler', () => {
}
`)
})

test('plugins can be created using the `createPlugin` function', () => {
const plugin = createPlugin(
function({ addUtilities, theme, variants }) {
const utilities = _.fromPairs(
_.toPairs(theme('testPlugin')).map(([k, v]) => [`.test-${k}`, { testProperty: v }])
)

addUtilities(utilities, variants('testPlugin'))
},
{
theme: {
testPlugin: {
sm: '1rem',
md: '2rem',
lg: '3rem',
},
},
variants: {
testPlugin: ['responsive', 'hover'],
},
}
)

return _postcss([
tailwind({
corePlugins: [],
theme: {
screens: {
sm: '400px',
},
},
plugins: [plugin],
}),
])
.process(
`
@tailwind base;
@tailwind components;
@tailwind utilities;
`,
{ from: undefined }
)
.then(result => {
const expected = `
.test-sm {
test-property: 1rem
}
.test-md {
test-property: 2rem
}
.test-lg {
test-property: 3rem
}
.hover\\:test-sm:hover {
test-property: 1rem
}
.hover\\:test-md:hover {
test-property: 2rem
}
.hover\\:test-lg:hover {
test-property: 3rem
}

@media (min-width: 400px) {
.sm\\:test-sm {
test-property: 1rem
}
.sm\\:test-md {
test-property: 2rem
}
.sm\\:test-lg {
test-property: 3rem
}
.sm\\:hover\\:test-sm:hover {
test-property: 1rem
}
.sm\\:hover\\:test-md:hover {
test-property: 2rem
}
.sm\\:hover\\:test-lg:hover {
test-property: 3rem
}
}
`

expect(result.css).toMatchCss(expected)
})
})

test('plugins with extra options can be created using the `createPlugin.withOptions` function', () => {
const plugin = createPlugin.withOptions(
function({ className }) {
return function({ addUtilities, theme, variants }) {
const utilities = _.fromPairs(
_.toPairs(theme('testPlugin')).map(([k, v]) => [
`.${className}-${k}`,
{ testProperty: v },
])
)

addUtilities(utilities, variants('testPlugin'))
}
},
function() {
return {
theme: {
testPlugin: {
sm: '1rem',
md: '2rem',
lg: '3rem',
},
},
variants: {
testPlugin: ['responsive', 'hover'],
},
}
}
)

return _postcss([
tailwind({
corePlugins: [],
theme: {
screens: {
sm: '400px',
},
},
plugins: [plugin({ className: 'banana' })],
}),
])
.process(
`
@tailwind base;
@tailwind components;
@tailwind utilities;
`,
{ from: undefined }
)
.then(result => {
const expected = `
.banana-sm {
test-property: 1rem
}
.banana-md {
test-property: 2rem
}
.banana-lg {
test-property: 3rem
}
.hover\\:banana-sm:hover {
test-property: 1rem
}
.hover\\:banana-md:hover {
test-property: 2rem
}
.hover\\:banana-lg:hover {
test-property: 3rem
}

@media (min-width: 400px) {
.sm\\:banana-sm {
test-property: 1rem
}
.sm\\:banana-md {
test-property: 2rem
}
.sm\\:banana-lg {
test-property: 3rem
}
.sm\\:hover\\:banana-sm:hover {
test-property: 1rem
}
.sm\\:hover\\:banana-md:hover {
test-property: 2rem
}
.sm\\:hover\\:banana-lg:hover {
test-property: 3rem
}
}
`

expect(result.css).toMatchCss(expected)
})
})

test('plugins created using `createPlugin.withOptions` do not need to be invoked if the user wants to use the default options', () => {
const plugin = createPlugin.withOptions(
function({ className } = { className: 'banana' }) {
return function({ addUtilities, theme, variants }) {
const utilities = _.fromPairs(
_.toPairs(theme('testPlugin')).map(([k, v]) => [
`.${className}-${k}`,
{ testProperty: v },
])
)

addUtilities(utilities, variants('testPlugin'))
}
},
function() {
return {
theme: {
testPlugin: {
sm: '1rem',
md: '2rem',
lg: '3rem',
},
},
variants: {
testPlugin: ['responsive', 'hover'],
},
}
}
)

return _postcss([
tailwind({
corePlugins: [],
theme: {
screens: {
sm: '400px',
},
},
plugins: [plugin],
}),
])
.process(
`
@tailwind base;
@tailwind components;
@tailwind utilities;
`,
{ from: undefined }
)
.then(result => {
const expected = `
.banana-sm {
test-property: 1rem
}
.banana-md {
test-property: 2rem
}
.banana-lg {
test-property: 3rem
}
.hover\\:banana-sm:hover {
test-property: 1rem
}
.hover\\:banana-md:hover {
test-property: 2rem
}
.hover\\:banana-lg:hover {
test-property: 3rem
}

@media (min-width: 400px) {
.sm\\:banana-sm {
test-property: 1rem
}
.sm\\:banana-md {
test-property: 2rem
}
.sm\\:banana-lg {
test-property: 3rem
}
.sm\\:hover\\:banana-sm:hover {
test-property: 1rem
}
.sm\\:hover\\:banana-md:hover {
test-property: 2rem
}
.sm\\:hover\\:banana-lg:hover {
test-property: 3rem
}
}
`

expect(result.css).toMatchCss(expected)
})
})
3 changes: 3 additions & 0 deletions plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const createPlugin = require('./lib/util/createPlugin').default

module.exports = createPlugin
21 changes: 21 additions & 0 deletions src/util/createPlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
function createPlugin(plugin, config) {
return {
handler: plugin,
config,
}
}

createPlugin.withOptions = function(pluginFunction, configFunction) {
const optionsFunction = function(options) {
return {
handler: pluginFunction(options),
config: configFunction(options),
}
}

optionsFunction.__isOptionsFunction = true

return optionsFunction
}

export default createPlugin
4 changes: 4 additions & 0 deletions src/util/processPlugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ export default function(plugins, config) {
const getConfigValue = (path, defaultValue) => _.get(config, path, defaultValue)

plugins.forEach(plugin => {
if (plugin.__isOptionsFunction) {
plugin = plugin()
}

const handler = isFunction(plugin) ? plugin : _.get(plugin, 'handler', () => {})

handler({
Expand Down
3 changes: 3 additions & 0 deletions src/util/resolveConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ function extractPluginConfigs(configs) {
}

plugins.forEach(plugin => {
if (plugin.__isOptionsFunction) {
plugin = plugin()
}
allConfigs = [...allConfigs, ...extractPluginConfigs([get(plugin, 'config', {})])]
})
})
Expand Down