diff --git a/__tests__/applyAtRule.test.js b/__tests__/applyAtRule.test.js index 652b44940ac2..1829a3f9dd0a 100644 --- a/__tests__/applyAtRule.test.js +++ b/__tests__/applyAtRule.test.js @@ -1,14 +1,14 @@ import postcss from 'postcss' import plugin from '../src/lib/substituteClassApplyAtRules' -function run(input, opts) { +function run(input, opts = () => {}) { return postcss([plugin(opts)]).process(input) } test("it copies a class's declarations into itself", () => { const output = '.a { color: red; } .b { color: red; }' - return run('.a { color: red; } .b { @apply .a; }', {}).then(result => { + return run('.a { color: red; } .b { @apply .a; }').then(result => { expect(result.css).toEqual(output) expect(result.warnings().length).toBe(0) }) @@ -38,16 +38,15 @@ test("it doesn't copy a media query definition into itself", () => { .b { @apply .a; - }`, - {} - ).then(result => { + }`) + .then(result => { expect(result.css).toEqual(output) expect(result.warnings().length).toBe(0) }) }) test('it fails if the class does not exist', () => { - run('.b { @apply .a; }', {}).catch(error => { + run('.b { @apply .a; }').catch(error => { expect(error.reason).toEqual('No .a class found.') }) }) diff --git a/__tests__/focusableAtRule.test.js b/__tests__/focusableAtRule.test.js index 51cdda2131dc..04fb8ba64f8c 100644 --- a/__tests__/focusableAtRule.test.js +++ b/__tests__/focusableAtRule.test.js @@ -1,7 +1,7 @@ import postcss from 'postcss' import plugin from '../src/lib/substituteFocusableAtRules' -function run(input, opts = {}) { +function run(input, opts = () => {}) { return postcss([plugin(opts)]).process(input) } @@ -18,7 +18,7 @@ test("it adds a focusable variant to each nested class definition", () => { .chocolate, .focus\\:chocolate:focus { color: brown; } ` - return run(input, {}).then(result => { + return run(input).then(result => { expect(result.css).toEqual(output) expect(result.warnings().length).toBe(0) }) diff --git a/__tests__/hoverableAtRule.test.js b/__tests__/hoverableAtRule.test.js index cd6747bd8995..afcd5096f8df 100644 --- a/__tests__/hoverableAtRule.test.js +++ b/__tests__/hoverableAtRule.test.js @@ -1,7 +1,7 @@ import postcss from 'postcss' import plugin from '../src/lib/substituteHoverableAtRules' -function run(input, opts = {}) { +function run(input, opts = () => {}) { return postcss([plugin(opts)]).process(input) } @@ -18,7 +18,7 @@ test("it adds a hoverable variant to each nested class definition", () => { .chocolate, .hover\\:chocolate:hover { color: brown; } ` - return run(input, {}).then(result => { + return run(input).then(result => { expect(result.css).toEqual(output) expect(result.warnings().length).toBe(0) }) diff --git a/docs/tailwind.js b/docs/tailwind.js index 7b45b53b0790..50f51d81414a 100644 --- a/docs/tailwind.js +++ b/docs/tailwind.js @@ -1,4 +1,4 @@ -var config = require('../defaultConfig') +var config = require('../lib/index').defaultConfig() config.colors = { ...config.colors, diff --git a/src/index.js b/src/index.js index cc02186bbb6c..f0899fe77f99 100644 --- a/src/index.js +++ b/src/index.js @@ -5,6 +5,7 @@ import _ from 'lodash' import postcss from 'postcss' import stylefmt from 'stylefmt' +import registerConfigAsDependency from './lib/registerConfigAsDependency' import substitutePreflightAtRule from './lib/substitutePreflightAtRule' import evaluateTailwindFunctions from './lib/evaluateTailwindFunctions' import generateUtilities from './lib/generateUtilities' @@ -15,23 +16,30 @@ import substituteScreenAtRules from './lib/substituteScreenAtRules' import substituteClassApplyAtRules from './lib/substituteClassApplyAtRules' const plugin = postcss.plugin('tailwind', (config) => { - if (_.isUndefined(config)) { - config = require('../defaultConfig') + const plugins = [] + + if (! _.isUndefined(config)) { + plugins.push(registerConfigAsDependency(path.resolve(config))) } - if (_.isString(config)) { - config = require(path.resolve(config)) + const lazyConfig = () => { + if (_.isUndefined(config)) { + return require('../defaultConfig') + } + + delete require.cache[require.resolve(path.resolve(config))] + return require(path.resolve(config)) } - return postcss([ - substitutePreflightAtRule(config), - evaluateTailwindFunctions(config), - generateUtilities(config), - substituteHoverableAtRules(config), - substituteFocusableAtRules(config), - substituteResponsiveAtRules(config), - substituteScreenAtRules(config), - substituteClassApplyAtRules(config), + return postcss(...plugins, ...[ + substitutePreflightAtRule(lazyConfig), + evaluateTailwindFunctions(lazyConfig), + generateUtilities(lazyConfig), + substituteHoverableAtRules(lazyConfig), + substituteFocusableAtRules(lazyConfig), + substituteResponsiveAtRules(lazyConfig), + substituteScreenAtRules(lazyConfig), + substituteClassApplyAtRules(lazyConfig), stylefmt, ]) }) diff --git a/src/lib/evaluateTailwindFunctions.js b/src/lib/evaluateTailwindFunctions.js index c89e246eeea4..3b2ab34863ad 100644 --- a/src/lib/evaluateTailwindFunctions.js +++ b/src/lib/evaluateTailwindFunctions.js @@ -1,7 +1,9 @@ import _ from 'lodash' import functions from 'postcss-functions' -export default function(options) { +export default function(config) { + const options = config() + return functions({ functions: { config: function (path) { diff --git a/src/lib/generateUtilities.js b/src/lib/generateUtilities.js index b5c6c5e4a1eb..bf658fcc048a 100644 --- a/src/lib/generateUtilities.js +++ b/src/lib/generateUtilities.js @@ -37,8 +37,10 @@ import verticalAlign from '../generators/verticalAlign' import visibility from '../generators/visibility' import zIndex from '../generators/zIndex' -export default function(options) { +export default function(config) { return function(css) { + const options = config() + css.walkAtRules('tailwind', atRule => { if (atRule.params === 'utilities') { const utilities = _.flatten([ diff --git a/src/lib/registerConfigAsDependency.js b/src/lib/registerConfigAsDependency.js new file mode 100644 index 000000000000..589db20ed52a --- /dev/null +++ b/src/lib/registerConfigAsDependency.js @@ -0,0 +1,15 @@ +import fs from 'fs' + +export default function(configFile) { + if (! fs.existsSync(configFile)) { + throw new Error(`Specified Tailwind config file "${configFile}" doesn't exist.`) + } + + return function (css, opts) { + opts.messages = [{ + type: 'dependency', + file: configFile, + parent: css.source.input.file, + }] + } +} diff --git a/src/lib/substituteClassApplyAtRules.js b/src/lib/substituteClassApplyAtRules.js index 7d506d7a2e23..ff3568c4db48 100644 --- a/src/lib/substituteClassApplyAtRules.js +++ b/src/lib/substituteClassApplyAtRules.js @@ -9,8 +9,9 @@ function normalizeClassNames(classNames) { }) } -export default postcss.plugin('tailwind-apply', function(css) { - return function(css) { +export default function(config) { + return function (css) { + const options = config() css.walkRules(function(rule) { rule.walkAtRules('apply', atRule => { const mixins = normalizeClassNames(postcss.list.space(atRule.params)) @@ -42,4 +43,4 @@ export default postcss.plugin('tailwind-apply', function(css) { }) }) } -}) +} diff --git a/src/lib/substituteFocusableAtRules.js b/src/lib/substituteFocusableAtRules.js index c12aa2b6c8f8..10cf04e2f82f 100644 --- a/src/lib/substituteFocusableAtRules.js +++ b/src/lib/substituteFocusableAtRules.js @@ -2,8 +2,10 @@ import _ from 'lodash' import postcss from 'postcss' import cloneNodes from '../util/cloneNodes' -export default function(options) { - return function(css) { +export default function(config) { + return function (css) { + const options = config() + css.walkAtRules('focusable', atRule => { atRule.walkRules(rule => { diff --git a/src/lib/substituteHoverableAtRules.js b/src/lib/substituteHoverableAtRules.js index e4d419e2ac13..abe432d70b85 100644 --- a/src/lib/substituteHoverableAtRules.js +++ b/src/lib/substituteHoverableAtRules.js @@ -2,8 +2,10 @@ import _ from 'lodash' import postcss from 'postcss' import cloneNodes from '../util/cloneNodes' -export default function(options) { - return function(css) { +export default function(config) { + return function (css) { + const options = config() + css.walkAtRules('hoverable', atRule => { atRule.walkRules(rule => { diff --git a/src/lib/substitutePreflightAtRule.js b/src/lib/substitutePreflightAtRule.js index 18478d0ef217..62e01a49a62b 100644 --- a/src/lib/substitutePreflightAtRule.js +++ b/src/lib/substitutePreflightAtRule.js @@ -1,8 +1,10 @@ import fs from 'fs' import postcss from 'postcss' -export default function(options) { +export default function(config) { return function (css) { + const options = config() + css.walkAtRules('tailwind', atRule => { if (atRule.params === 'preflight') { atRule.before(postcss.parse(fs.readFileSync(`${__dirname}/../../css/preflight.css`, 'utf8'))) diff --git a/src/lib/substituteResponsiveAtRules.js b/src/lib/substituteResponsiveAtRules.js index 837035edf8c7..98b306c3f807 100644 --- a/src/lib/substituteResponsiveAtRules.js +++ b/src/lib/substituteResponsiveAtRules.js @@ -3,8 +3,10 @@ import postcss from 'postcss' import cloneNodes from '../util/cloneNodes' import buildMediaQuery from '../util/buildMediaQuery' -export default function({ screens }) { - return function(css) { + +export default function(config) { + return function (css) { + const screens = config().screens const rules = [] css.walkAtRules('responsive', atRule => { diff --git a/src/lib/substituteScreenAtRules.js b/src/lib/substituteScreenAtRules.js index 67d9de91067e..951492e8fb85 100644 --- a/src/lib/substituteScreenAtRules.js +++ b/src/lib/substituteScreenAtRules.js @@ -3,8 +3,9 @@ import postcss from 'postcss' import cloneNodes from '../util/cloneNodes' import buildMediaQuery from '../util/buildMediaQuery' -export default function(options) { +export default function(config) { return function(css) { + const options = config() const rules = [] css.walkAtRules('screen', atRule => {