Merge pull request #233 from tailwindcss/modularize

Allow enabling/disabling modules and specifying variants from config file
This commit is contained in:
Adam Wathan 2017-11-24 09:25:27 -05:00 committed by GitHub
commit 45eff6578b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 8288 additions and 8032 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,133 @@
import generateModules from '../src/util/generateModules'
import defineClasses from '../src/util/defineClasses'
function textAlign() {
return defineClasses({
'text-left': { 'text-align': 'left' },
'text-right': { 'text-align': 'right' },
'text-center': { 'text-align': 'center' },
})
}
function display() {
return defineClasses({
block: { display: 'block' },
inline: { display: 'inline' },
'inline-block': { display: 'inline-block' },
})
}
function borderStyle() {
return defineClasses({
'border-solid': { 'border-style': 'solid' },
'border-dashed': { 'border-style': 'dashed' },
'border-dotted': { 'border-style': 'dotted' },
})
}
test('an empty variants list generates a @variants at-rule with no parameters', () => {
const result = generateModules([{ name: 'textAlign', generator: textAlign }], {
textAlign: [],
})
const expected = `
@variants {
.text-left { text-align: left }
.text-right { text-align: right }
.text-center { text-align: center }
}
`
expect(result.toString()).toMatchCss(expected)
})
test('a `false` variants list generates no output', () => {
const result = generateModules([{ name: 'textAlign', generator: textAlign }], {
textAlign: false,
})
expect(result.toString()).toMatchCss('')
})
test('specified variants are included in the @variants at-rule', () => {
const result = generateModules([{ name: 'textAlign', generator: textAlign }], {
textAlign: ['responsive', 'hover'],
})
const expected = `
@variants responsive, hover {
.text-left { text-align: left }
.text-right { text-align: right }
.text-center { text-align: center }
}
`
expect(result.toString()).toMatchCss(expected)
})
test('options must provide variants for every module', () => {
expect(() => {
generateModules(
[{ name: 'textAlign', generator: textAlign }, { name: 'display', generator: display }],
{
textAlign: [],
}
)
}).toThrow()
})
test('variants can be different for each module', () => {
const result = generateModules(
[
{ name: 'textAlign', generator: textAlign },
{ name: 'display', generator: display },
{ name: 'borderStyle', generator: borderStyle },
],
{
textAlign: [],
display: false,
borderStyle: ['responsive', 'hover', 'focus'],
}
)
const expected = `
@variants {
.text-left { text-align: left }
.text-right { text-align: right }
.text-center { text-align: center }
}
@variants responsive, hover, focus {
.border-solid { border-style: solid }
.border-dashed { border-style: dashed }
.border-dotted { border-style: dotted }
}
`
expect(result.toString()).toMatchCss(expected)
})
test('generators can reference the generatorOptions object', () => {
const result = generateModules(
[
{
name: 'parameterized',
generator: generatorParams => {
return defineClasses({
foo: { color: generatorParams.color },
})
},
},
],
{
parameterized: [],
},
{
color: 'blue',
}
)
const expected = `
@variants {
.foo { color: blue }
}
`
expect(result.toString()).toMatchCss(expected)
})

View File

@ -770,6 +770,49 @@ module.exports = {
options: {
prefix: '',
important: false,
modules: {
appearance: ['responsive'],
backgroundColors: ['responsive', 'hover'],
backgroundPosition: ['responsive'],
backgroundSize: ['responsive'],
borderColors: ['responsive', 'hover'],
borderRadius: ['responsive'],
borderStyle: ['responsive'],
borderWidths: ['responsive'],
cursor: ['responsive'],
display: ['responsive'],
flexbox: ['responsive'],
float: ['responsive'],
fonts: ['responsive'],
fontWeights: ['responsive', 'hover'],
height: ['responsive'],
leading: ['responsive'],
lists: ['responsive'],
margin: ['responsive'],
maxHeight: ['responsive'],
maxWidth: ['responsive'],
minHeight: ['responsive'],
minWidth: ['responsive'],
negativeMargin: ['responsive'],
opacity: ['responsive'],
overflow: ['responsive'],
padding: ['responsive'],
pointerEvents: ['responsive'],
position: ['responsive'],
resize: ['responsive'],
shadows: ['responsive'],
textAlign: ['responsive'],
textColors: ['responsive', 'hover'],
textSizes: ['responsive'],
textStyle: ['responsive', 'hover'],
tracking: ['responsive'],
userSelect: ['responsive'],
verticalAlign: ['responsive'],
visibility: ['responsive'],
whitespace: ['responsive'],
width: ['responsive'],
zIndex: ['responsive'],
}
},
}

View File

@ -1,13 +1,10 @@
import _ from 'lodash'
import defineClass from '../util/defineClass'
import hoverable from '../util/hoverable'
export default function({ backgroundColors }) {
return hoverable(
_.map(backgroundColors, (color, className) => {
return defineClass(`bg-${className}`, {
'background-color': color,
})
return _.map(backgroundColors, (color, className) => {
return defineClass(`bg-${className}`, {
'background-color': color,
})
)
})
}

View File

@ -1,13 +1,10 @@
import _ from 'lodash'
import defineClass from '../util/defineClass'
import hoverable from '../util/hoverable'
export default function({ borderColors }) {
return hoverable(
_.map(_.omit(borderColors, 'default'), (color, className) => {
return defineClass(`border-${className}`, {
'border-color': color,
})
return _.map(_.omit(borderColors, 'default'), (color, className) => {
return defineClass(`border-${className}`, {
'border-color': color,
})
)
})
}

View File

@ -0,0 +1,10 @@
import _ from 'lodash'
import defineClass from '../util/defineClass'
export default function({ fontWeights }) {
return _.map(fontWeights, (weight, modifier) => {
return defineClass(`font-${modifier}`, {
'font-weight': `${weight}`,
})
})
}

14
src/generators/height.js Normal file
View File

@ -0,0 +1,14 @@
import _ from 'lodash'
import defineClass from '../util/defineClass'
function defineHeights(heights) {
return _.map(heights, (size, modifer) => {
return defineClass(`h-${modifer}`, {
height: `${size}`,
})
})
}
export default function(config) {
return _.flatten([defineHeights(config.height)])
}

31
src/generators/margin.js Normal file
View File

@ -0,0 +1,31 @@
import _ from 'lodash'
import defineClasses from '../util/defineClasses'
function defineMargin(margin) {
const generators = [
(size, modifier) =>
defineClasses({
[`m-${modifier}`]: { margin: `${size}` },
}),
(size, modifier) =>
defineClasses({
[`my-${modifier}`]: { 'margin-top': `${size}`, 'margin-bottom': `${size}` },
[`mx-${modifier}`]: { 'margin-left': `${size}`, 'margin-right': `${size}` },
}),
(size, modifier) =>
defineClasses({
[`mt-${modifier}`]: { 'margin-top': `${size}` },
[`mr-${modifier}`]: { 'margin-right': `${size}` },
[`mb-${modifier}`]: { 'margin-bottom': `${size}` },
[`ml-${modifier}`]: { 'margin-left': `${size}` },
}),
]
return _.flatMap(generators, generator => {
return _.flatMap(margin, generator)
})
}
export default function({ margin }) {
return _.flatten([defineMargin(margin)])
}

View File

@ -0,0 +1,14 @@
import _ from 'lodash'
import defineClass from '../util/defineClass'
function defineMaxHeights(heights) {
return _.map(heights, (size, modifer) => {
return defineClass(`max-h-${modifer}`, {
'max-height': `${size}`,
})
})
}
export default function(config) {
return _.flatten([defineMaxHeights(config.maxHeight)])
}

View File

@ -0,0 +1,14 @@
import _ from 'lodash'
import defineClass from '../util/defineClass'
function defineMaxWidths(widths) {
return _.map(widths, (size, modifer) => {
return defineClass(`max-w-${modifer}`, {
'max-width': `${size}`,
})
})
}
export default function(config) {
return _.flatten([defineMaxWidths(config.maxWidth)])
}

View File

@ -0,0 +1,14 @@
import _ from 'lodash'
import defineClass from '../util/defineClass'
function defineMinHeights(heights) {
return _.map(heights, (size, modifer) => {
return defineClass(`min-h-${modifer}`, {
'min-height': `${size}`,
})
})
}
export default function(config) {
return _.flatten([defineMinHeights(config.minHeight)])
}

View File

@ -0,0 +1,14 @@
import _ from 'lodash'
import defineClass from '../util/defineClass'
function defineMinWidths(widths) {
return _.map(widths, (size, modifer) => {
return defineClass(`min-w-${modifer}`, {
'min-width': `${size}`,
})
})
}
export default function(config) {
return _.flatten([defineMinWidths(config.minWidth)])
}

View File

@ -0,0 +1,33 @@
import _ from 'lodash'
import defineClasses from '../util/defineClasses'
function defineNegativeMargin(negativeMargin) {
const generators = [
(size, modifier) =>
defineClasses({
[`-m-${modifier}`]: { margin: `${size}` },
}),
(size, modifier) =>
defineClasses({
[`-my-${modifier}`]: { 'margin-top': `${size}`, 'margin-bottom': `${size}` },
[`-mx-${modifier}`]: { 'margin-left': `${size}`, 'margin-right': `${size}` },
}),
(size, modifier) =>
defineClasses({
[`-mt-${modifier}`]: { 'margin-top': `${size}` },
[`-mr-${modifier}`]: { 'margin-right': `${size}` },
[`-mb-${modifier}`]: { 'margin-bottom': `${size}` },
[`-ml-${modifier}`]: { 'margin-left': `${size}` },
}),
]
return _.flatMap(generators, generator => {
return _.flatMap(negativeMargin, (size, modifier) => {
return generator(`${size}` === '0' ? `${size}` : `-${size}`, modifier)
})
})
}
export default function({ negativeMargin }) {
return _.flatten([defineNegativeMargin(negativeMargin)])
}

31
src/generators/padding.js Normal file
View File

@ -0,0 +1,31 @@
import _ from 'lodash'
import defineClasses from '../util/defineClasses'
function definePadding(padding) {
const generators = [
(size, modifier) =>
defineClasses({
[`p-${modifier}`]: { padding: `${size}` },
}),
(size, modifier) =>
defineClasses({
[`py-${modifier}`]: { 'padding-top': `${size}`, 'padding-bottom': `${size}` },
[`px-${modifier}`]: { 'padding-left': `${size}`, 'padding-right': `${size}` },
}),
(size, modifier) =>
defineClasses({
[`pt-${modifier}`]: { 'padding-top': `${size}` },
[`pr-${modifier}`]: { 'padding-right': `${size}` },
[`pb-${modifier}`]: { 'padding-bottom': `${size}` },
[`pl-${modifier}`]: { 'padding-left': `${size}` },
}),
]
return _.flatMap(generators, generator => {
return _.flatMap(padding, generator)
})
}
export default function({ padding }) {
return _.flatten([definePadding(padding)])
}

View File

@ -1,61 +0,0 @@
import _ from 'lodash'
import defineClass from '../util/defineClass'
function defineWidths(widths) {
return _.map(widths, (size, modifer) => {
return defineClass(`w-${modifer}`, {
width: `${size}`,
})
})
}
function defineMinWidths(widths) {
return _.map(widths, (size, modifer) => {
return defineClass(`min-w-${modifer}`, {
'min-width': `${size}`,
})
})
}
function defineMaxWidths(widths) {
return _.map(widths, (size, modifer) => {
return defineClass(`max-w-${modifer}`, {
'max-width': `${size}`,
})
})
}
function defineHeights(heights) {
return _.map(heights, (size, modifer) => {
return defineClass(`h-${modifer}`, {
height: `${size}`,
})
})
}
function defineMinHeights(heights) {
return _.map(heights, (size, modifer) => {
return defineClass(`min-h-${modifer}`, {
'min-height': `${size}`,
})
})
}
function defineMaxHeights(heights) {
return _.map(heights, (size, modifer) => {
return defineClass(`max-h-${modifer}`, {
'max-height': `${size}`,
})
})
}
export default function(config) {
return _.flatten([
defineWidths(config.width),
defineMinWidths(config.minWidth),
defineMaxWidths(config.maxWidth),
defineHeights(config.height),
defineMinHeights(config.minHeight),
defineMaxHeights(config.maxHeight),
])
}

View File

@ -1,87 +0,0 @@
import _ from 'lodash'
import defineClasses from '../util/defineClasses'
function definePadding(padding) {
const generators = [
(size, modifier) =>
defineClasses({
[`p-${modifier}`]: { padding: `${size}` },
}),
(size, modifier) =>
defineClasses({
[`py-${modifier}`]: { 'padding-top': `${size}`, 'padding-bottom': `${size}` },
[`px-${modifier}`]: { 'padding-left': `${size}`, 'padding-right': `${size}` },
}),
(size, modifier) =>
defineClasses({
[`pt-${modifier}`]: { 'padding-top': `${size}` },
[`pr-${modifier}`]: { 'padding-right': `${size}` },
[`pb-${modifier}`]: { 'padding-bottom': `${size}` },
[`pl-${modifier}`]: { 'padding-left': `${size}` },
}),
]
return _.flatMap(generators, generator => {
return _.flatMap(padding, generator)
})
}
function defineMargin(margin) {
const generators = [
(size, modifier) =>
defineClasses({
[`m-${modifier}`]: { margin: `${size}` },
}),
(size, modifier) =>
defineClasses({
[`my-${modifier}`]: { 'margin-top': `${size}`, 'margin-bottom': `${size}` },
[`mx-${modifier}`]: { 'margin-left': `${size}`, 'margin-right': `${size}` },
}),
(size, modifier) =>
defineClasses({
[`mt-${modifier}`]: { 'margin-top': `${size}` },
[`mr-${modifier}`]: { 'margin-right': `${size}` },
[`mb-${modifier}`]: { 'margin-bottom': `${size}` },
[`ml-${modifier}`]: { 'margin-left': `${size}` },
}),
]
return _.flatMap(generators, generator => {
return _.flatMap(margin, generator)
})
}
function defineNegativeMargin(negativeMargin) {
const generators = [
(size, modifier) =>
defineClasses({
[`-m-${modifier}`]: { margin: `${size}` },
}),
(size, modifier) =>
defineClasses({
[`-my-${modifier}`]: { 'margin-top': `${size}`, 'margin-bottom': `${size}` },
[`-mx-${modifier}`]: { 'margin-left': `${size}`, 'margin-right': `${size}` },
}),
(size, modifier) =>
defineClasses({
[`-mt-${modifier}`]: { 'margin-top': `${size}` },
[`-mr-${modifier}`]: { 'margin-right': `${size}` },
[`-mb-${modifier}`]: { 'margin-bottom': `${size}` },
[`-ml-${modifier}`]: { 'margin-left': `${size}` },
}),
]
return _.flatMap(generators, generator => {
return _.flatMap(negativeMargin, (size, modifier) => {
return generator(`${size}` === '0' ? `${size}` : `-${size}`, modifier)
})
})
}
export default function({ padding, margin, negativeMargin }) {
return _.flatten([
definePadding(padding),
defineMargin(margin),
defineNegativeMargin(negativeMargin),
])
}

View File

@ -1,13 +1,10 @@
import _ from 'lodash'
import defineClass from '../util/defineClass'
import hoverable from '../util/hoverable'
export default function({ textColors }) {
return hoverable(
_.map(textColors, (color, modifier) => {
return defineClass(`text-${modifier}`, {
color,
})
return _.map(textColors, (color, modifier) => {
return defineClass(`text-${modifier}`, {
color,
})
)
})
}

View File

@ -1,29 +1,26 @@
import defineClasses from '../util/defineClasses'
import hoverable from '../util/hoverable'
export default function() {
return hoverable(
defineClasses({
italic: { 'font-style': 'italic' },
roman: { 'font-style': 'normal' },
return defineClasses({
italic: { 'font-style': 'italic' },
roman: { 'font-style': 'normal' },
uppercase: { 'text-transform': 'uppercase' },
lowercase: { 'text-transform': 'lowercase' },
capitalize: { 'text-transform': 'capitalize' },
'normal-case': { 'text-transform': 'none' },
uppercase: { 'text-transform': 'uppercase' },
lowercase: { 'text-transform': 'lowercase' },
capitalize: { 'text-transform': 'capitalize' },
'normal-case': { 'text-transform': 'none' },
underline: { 'text-decoration': 'underline' },
'line-through': { 'text-decoration': 'line-through' },
'no-underline': { 'text-decoration': 'none' },
underline: { 'text-decoration': 'underline' },
'line-through': { 'text-decoration': 'line-through' },
'no-underline': { 'text-decoration': 'none' },
antialiased: {
'-webkit-font-smoothing': 'antialiased',
'-moz-osx-font-smoothing': 'grayscale',
},
'subpixel-antialiased': {
'-webkit-font-smoothing': 'auto',
'-moz-osx-font-smoothing': 'auto',
},
})
)
antialiased: {
'-webkit-font-smoothing': 'antialiased',
'-moz-osx-font-smoothing': 'grayscale',
},
'subpixel-antialiased': {
'-webkit-font-smoothing': 'auto',
'-moz-osx-font-smoothing': 'auto',
},
})
}

View File

@ -1,13 +0,0 @@
import _ from 'lodash'
import defineClass from '../util/defineClass'
import hoverable from '../util/hoverable'
export default function({ fontWeights }) {
return hoverable(
_.map(fontWeights, (weight, modifier) => {
return defineClass(`font-${modifier}`, {
'font-weight': `${weight}`,
})
})
)
}

14
src/generators/width.js Normal file
View File

@ -0,0 +1,14 @@
import _ from 'lodash'
import defineClass from '../util/defineClass'
function defineWidths(widths) {
return _.map(widths, (size, modifer) => {
return defineClass(`w-${modifer}`, {
width: `${size}`,
})
})
}
export default function(config) {
return _.flatten([defineWidths(config.width)])
}

View File

@ -5,15 +5,24 @@ import postcss from 'postcss'
import stylefmt from 'stylefmt'
import registerConfigAsDependency from './lib/registerConfigAsDependency'
import substitutePreflightAtRule from './lib/substitutePreflightAtRule'
import substituteTailwindPreflightAtRule from './lib/substituteTailwindPreflightAtRule'
import evaluateTailwindFunctions from './lib/evaluateTailwindFunctions'
import generateUtilities from './lib/generateUtilities'
import substituteTailwindUtilitiesAtRules from './lib/substituteTailwindUtilitiesAtRules'
import substituteHoverableAtRules from './lib/substituteHoverableAtRules'
import substituteFocusableAtRules from './lib/substituteFocusableAtRules'
import substituteVariantsAtRules from './lib/substituteVariantsAtRules'
import substituteResponsiveAtRules from './lib/substituteResponsiveAtRules'
import substituteScreenAtRules from './lib/substituteScreenAtRules'
import substituteClassApplyAtRules from './lib/substituteClassApplyAtRules'
function mergeConfigWithDefaults(config) {
const defaultConfig = require('../defaultConfig')()
_.defaults(config, defaultConfig)
config.options = _.defaults(config.options, defaultConfig.options)
config.options.modules = _.defaults(config.options.modules, defaultConfig.options.modules)
return config
}
const plugin = postcss.plugin('tailwind', config => {
const plugins = []
@ -27,17 +36,18 @@ const plugin = postcss.plugin('tailwind', config => {
}
delete require.cache[require.resolve(path.resolve(config))]
return require(path.resolve(config))
return mergeConfigWithDefaults(require(path.resolve(config)))
}
return postcss(
...plugins,
...[
substitutePreflightAtRule(lazyConfig),
substituteTailwindPreflightAtRule(lazyConfig),
evaluateTailwindFunctions(lazyConfig),
generateUtilities(lazyConfig),
substituteTailwindUtilitiesAtRules(lazyConfig),
substituteHoverableAtRules(lazyConfig),
substituteFocusableAtRules(lazyConfig),
substituteVariantsAtRules(lazyConfig),
substituteResponsiveAtRules(lazyConfig),
substituteScreenAtRules(lazyConfig),
substituteClassApplyAtRules(lazyConfig),

View File

@ -1,101 +0,0 @@
import _ from 'lodash'
import postcss from 'postcss'
import applyClassPrefix from '../util/applyClassPrefix'
import backgroundColors from '../generators/backgroundColors'
import backgroundPositions from '../generators/backgroundPositions'
import backgroundSize from '../generators/backgroundSize'
import borderColors from '../generators/borderColors'
import borderStyles from '../generators/borderStyles'
import borderWidths from '../generators/borderWidths'
import container from '../generators/container'
import cursor from '../generators/cursor'
import display from '../generators/display'
import flex from '../generators/flex'
import floats from '../generators/floats'
import forms from '../generators/forms'
import lists from '../generators/lists'
import opacity from '../generators/opacity'
import overflow from '../generators/overflow'
import pointerEvents from '../generators/pointerEvents'
import position from '../generators/position'
import resize from '../generators/resize'
import responsive from '../util/responsive'
import rounded from '../generators/rounded'
import shadows from '../generators/shadows'
import sizing from '../generators/sizing'
import spacing from '../generators/spacing'
import textAlign from '../generators/textAlign'
import textColors from '../generators/textColors'
import textFonts from '../generators/textFonts'
import textLeading from '../generators/textLeading'
import textSizes from '../generators/textSizes'
import textStyle from '../generators/textStyle'
import textTracking from '../generators/textTracking'
import textWeights from '../generators/textWeights'
import textWrap from '../generators/textWrap'
import userSelect from '../generators/userSelect'
import verticalAlign from '../generators/verticalAlign'
import visibility from '../generators/visibility'
import zIndex from '../generators/zIndex'
export default function(config) {
return function(css) {
const unwrappedConfig = config()
css.walkAtRules('tailwind', atRule => {
if (atRule.params === 'utilities') {
const utilities = postcss.root({
nodes: _.flatten([
lists(unwrappedConfig),
forms(unwrappedConfig),
textSizes(unwrappedConfig),
textWeights(unwrappedConfig),
textFonts(unwrappedConfig),
textColors(unwrappedConfig),
textLeading(unwrappedConfig),
textTracking(unwrappedConfig),
textAlign(unwrappedConfig),
textWrap(unwrappedConfig),
textStyle(unwrappedConfig),
verticalAlign(unwrappedConfig),
backgroundColors(unwrappedConfig),
backgroundPositions(unwrappedConfig),
backgroundSize(unwrappedConfig),
borderWidths(unwrappedConfig),
borderColors(unwrappedConfig),
borderStyles(unwrappedConfig),
rounded(unwrappedConfig),
display(unwrappedConfig),
position(unwrappedConfig),
overflow(unwrappedConfig),
sizing(unwrappedConfig),
spacing(unwrappedConfig),
shadows(unwrappedConfig),
flex(unwrappedConfig),
floats(unwrappedConfig),
visibility(unwrappedConfig),
zIndex(unwrappedConfig),
opacity(unwrappedConfig),
userSelect(unwrappedConfig),
pointerEvents(unwrappedConfig),
resize(unwrappedConfig),
cursor(unwrappedConfig),
]),
})
if (_.get(unwrappedConfig, 'options.important', false)) {
utilities.walkDecls(decl => (decl.important = true))
}
const tailwindClasses = postcss.root({
nodes: [...container(unwrappedConfig), responsive(utilities)],
})
applyClassPrefix(tailwindClasses, _.get(unwrappedConfig, 'options.prefix', ''))
atRule.before(tailwindClasses)
atRule.remove()
}
})
}
}

View File

@ -1,15 +0,0 @@
import fs from 'fs'
import postcss from 'postcss'
export default function() {
return function(css) {
css.walkAtRules('tailwind', atRule => {
if (atRule.params === 'preflight') {
atRule.before(
postcss.parse(fs.readFileSync(`${__dirname}/../../css/preflight.css`, 'utf8'))
)
atRule.remove()
}
})
}
}

View File

@ -0,0 +1,15 @@
import fs from 'fs'
import postcss from 'postcss'
export default function() {
return function(css) {
css.walkAtRules('tailwind', atRule => {
if (atRule.params !== 'preflight') {
return
}
atRule.before(postcss.parse(fs.readFileSync(`${__dirname}/../../css/preflight.css`, 'utf8')))
atRule.remove()
})
}
}

View File

@ -0,0 +1,37 @@
import _ from 'lodash'
import postcss from 'postcss'
import applyClassPrefix from '../util/applyClassPrefix'
import generateModules from '../util/generateModules'
import container from '../generators/container'
import utilityModules from '../utilityModules'
export default function(config) {
return function(css) {
const unwrappedConfig = config()
css.walkAtRules('tailwind', atRule => {
if (atRule.params !== 'utilities') {
return
}
const utilities = generateModules(
utilityModules,
unwrappedConfig.options.modules,
unwrappedConfig
)
if (_.get(unwrappedConfig, 'options.important', false)) {
utilities.walkDecls(decl => (decl.important = true))
}
const tailwindClasses = postcss.root({
nodes: [...container(unwrappedConfig), ...utilities.nodes],
})
applyClassPrefix(tailwindClasses, _.get(unwrappedConfig, 'options.prefix', ''))
atRule.before(tailwindClasses)
atRule.remove()
})
}
}

View File

@ -0,0 +1,20 @@
import _ from 'lodash'
import postcss from 'postcss'
import wrapWithVariants from '../util/wrapWithVariants'
export default function(modules, moduleOptions, generatorOptions = {}) {
modules.forEach(module => {
if (!_.has(moduleOptions, module.name)) {
throw new Error(`Module \`${module.name}\` is missing from moduleOptions.`)
}
})
return postcss.root({
nodes: _(modules)
.reject(module => moduleOptions[module.name] === false)
.flatMap(module =>
wrapWithVariants(module.generator(generatorOptions), moduleOptions[module.name])
)
.value(),
})
}

View File

@ -1,3 +1,4 @@
import _ from 'lodash'
import postcss from 'postcss'
import cloneNodes from './cloneNodes'
@ -6,5 +7,5 @@ export default function hoverable(rules) {
.atRule({
name: 'hoverable',
})
.append(cloneNodes(rules))
.append(cloneNodes(_.isArray(rules) ? rules : [rules]))
}

View File

@ -7,5 +7,5 @@ export default function responsive(rules) {
.atRule({
name: 'responsive',
})
.append(cloneNodes(_.isArray(rules) ? rules : rules.nodes))
.append(cloneNodes(_.isArray(rules) ? rules : [rules]))
}

View File

@ -0,0 +1,12 @@
import _ from 'lodash'
import postcss from 'postcss'
import cloneNodes from './cloneNodes'
export default function wrapWithVariants(rules, variants) {
return postcss
.atRule({
name: 'variants',
params: variants.join(', '),
})
.append(cloneNodes(_.isArray(rules) ? rules : [rules]))
}

85
src/utilityModules.js Normal file
View File

@ -0,0 +1,85 @@
import lists from './generators/lists'
import appearance from './generators/appearance'
import backgroundColors from './generators/backgroundColors'
import backgroundPosition from './generators/backgroundPosition'
import backgroundSize from './generators/backgroundSize'
import borderColors from './generators/borderColors'
import borderRadius from './generators/borderRadius'
import borderStyle from './generators/borderStyle'
import borderWidths from './generators/borderWidths'
import cursor from './generators/cursor'
import display from './generators/display'
import flexbox from './generators/flexbox'
import float from './generators/float'
import fonts from './generators/fonts'
import fontWeights from './generators/fontWeights'
import height from './generators/height'
import leading from './generators/leading'
import margin from './generators/margin'
import maxHeight from './generators/maxHeight'
import maxWidth from './generators/maxWidth'
import minHeight from './generators/minHeight'
import minWidth from './generators/minWidth'
import negativeMargin from './generators/negativeMargin'
import opacity from './generators/opacity'
import overflow from './generators/overflow'
import padding from './generators/padding'
import pointerEvents from './generators/pointerEvents'
import position from './generators/position'
import resize from './generators/resize'
import shadows from './generators/shadows'
import textAlign from './generators/textAlign'
import textColors from './generators/textColors'
import textSizes from './generators/textSizes'
import textStyle from './generators/textStyle'
import tracking from './generators/tracking'
import userSelect from './generators/userSelect'
import verticalAlign from './generators/verticalAlign'
import visibility from './generators/visibility'
import whitespace from './generators/whitespace'
import width from './generators/width'
import zIndex from './generators/zIndex'
export default [
{ name: 'lists', generator: lists },
{ name: 'appearance', generator: appearance },
{ name: 'backgroundColors', generator: backgroundColors },
{ name: 'backgroundPosition', generator: backgroundPosition },
{ name: 'backgroundSize', generator: backgroundSize },
{ name: 'borderColors', generator: borderColors },
{ name: 'borderRadius', generator: borderRadius },
{ name: 'borderStyle', generator: borderStyle },
{ name: 'borderWidths', generator: borderWidths },
{ name: 'cursor', generator: cursor },
{ name: 'display', generator: display },
{ name: 'flexbox', generator: flexbox },
{ name: 'float', generator: float },
{ name: 'fonts', generator: fonts },
{ name: 'fontWeights', generator: fontWeights },
{ name: 'height', generator: height },
{ name: 'leading', generator: leading },
{ name: 'margin', generator: margin },
{ name: 'maxHeight', generator: maxHeight },
{ name: 'maxWidth', generator: maxWidth },
{ name: 'minHeight', generator: minHeight },
{ name: 'minWidth', generator: minWidth },
{ name: 'negativeMargin', generator: negativeMargin },
{ name: 'opacity', generator: opacity },
{ name: 'overflow', generator: overflow },
{ name: 'padding', generator: padding },
{ name: 'pointerEvents', generator: pointerEvents },
{ name: 'position', generator: position },
{ name: 'resize', generator: resize },
{ name: 'shadows', generator: shadows },
{ name: 'textAlign', generator: textAlign },
{ name: 'textColors', generator: textColors },
{ name: 'textSizes', generator: textSizes },
{ name: 'textStyle', generator: textStyle },
{ name: 'tracking', generator: tracking },
{ name: 'userSelect', generator: userSelect },
{ name: 'verticalAlign', generator: verticalAlign },
{ name: 'visibility', generator: visibility },
{ name: 'whitespace', generator: whitespace },
{ name: 'width', generator: width },
{ name: 'zIndex', generator: zIndex },
]