Break Tailwind out into 3 private plugins, bake in cssnext and stylefmt

This commit is contained in:
Adam Wathan 2017-08-26 11:18:50 -04:00
parent b33c76efe4
commit 1e1d45e092
5 changed files with 98 additions and 95 deletions

View File

@ -18,5 +18,8 @@
"postcss": "^6.0.9",
"postcss-cssnext": "^3.0.2",
"suitcss-base": "^3.0.0"
},
"devDependencies": {
"stylefmt": "^6.0.0"
}
}

View File

@ -1,35 +1,35 @@
const _ = require('lodash')
const postcss = require('postcss')
module.exports = function(css, {breakpoints}) {
function buildMediaQuery(breakpoint) {
if (_.isString(breakpoint)) {
breakpoint = {min: breakpoint}
}
return _(breakpoint)
.toPairs()
.map(([feature, value]) => {
feature = _.get(
{
min: 'min-width',
max: 'max-width',
},
feature,
feature
)
function buildMediaQuery(breakpoint) {
if (_.isString(breakpoint)) {
breakpoint = {min: breakpoint}
}
return `(${feature}: ${value})`
})
.join(' and ')
}
return _(breakpoint).toPairs().map(([feature, value]) => {
feature = _.get(
{
min: 'min-width',
max: 'max-width',
},
feature,
feature
)
Object.keys(breakpoints).forEach(breakpoint => {
const variableName = `--breakpoint-${breakpoint}`
const mediaQuery = buildMediaQuery(breakpoints[breakpoint])
const rule = postcss.atRule({
name: 'custom-media',
params: `${variableName} ${mediaQuery}`,
})
css.prepend(rule)
})
return `(${feature}: ${value})`
}).join(' and ')
}
module.exports = function ({breakpoints}) {
return function (css) {
Object.keys(breakpoints).forEach(breakpoint => {
const variableName = `--breakpoint-${breakpoint}`
const mediaQuery = buildMediaQuery(breakpoints[breakpoint])
const rule = postcss.atRule({
name: 'custom-media',
params: `${variableName} ${mediaQuery}`,
})
css.prepend(rule)
})
}
}

View File

@ -5,41 +5,43 @@ const shadows = require('../generators/shadows')
const flex = require('../generators/flex')
const cloneNodes = require('../util/cloneNodes')
module.exports = function(css, options) {
const rules = []
module.exports = function (options) {
return function (css) {
const rules = []
css.walkAtRules(atRule => {
if (atRule.name === 'responsive') {
const nodes = atRule.nodes
rules.push(...cloneNodes(nodes))
css.insertBefore(atRule, nodes)
atRule.remove()
}
if (atRule.name === 'tailwind' && atRule.params === 'utilities') {
const utilities = _.flatten([
backgroundColors(options),
shadows(options),
flex(),
])
rules.push(...cloneNodes(utilities))
css.insertBefore(atRule, utilities)
atRule.remove()
}
})
Object.keys(options.breakpoints).forEach(breakpoint => {
const mediaQuery = postcss.atRule({
name: 'media',
params: `(--breakpoint-${breakpoint})`,
css.walkAtRules(atRule => {
if (atRule.name === 'responsive') {
const nodes = atRule.nodes
rules.push(...cloneNodes(nodes))
css.insertBefore(atRule, nodes)
atRule.remove()
}
if (atRule.name === 'tailwind' && atRule.params === 'utilities') {
const utilities = _.flatten([
backgroundColors(options),
shadows(options),
flex(),
])
rules.push(...cloneNodes(utilities))
css.insertBefore(atRule, utilities)
atRule.remove()
}
})
mediaQuery.append(
rules.map(rule => {
const cloned = rule.clone()
cloned.selector = `.${breakpoint}\\:${rule.selector.slice(1)}`
return cloned
Object.keys(options.breakpoints).forEach(breakpoint => {
const mediaQuery = postcss.atRule({
name: 'media',
params: `(--breakpoint-${breakpoint})`,
})
)
css.append(mediaQuery)
})
mediaQuery.append(
rules.map(rule => {
const cloned = rule.clone()
cloned.selector = `.${breakpoint}\\:${rule.selector.slice(1)}`
return cloned
})
)
css.append(mediaQuery)
})
}
}

View File

@ -2,28 +2,30 @@ const postcss = require('postcss')
const _ = require('lodash')
const findMixin = require('../util/findMixin')
module.exports = function(css) {
css.walkRules(function(rule) {
rule.walkAtRules('apply', atRule => {
const mixins = postcss.list.space(atRule.params)
module.exports = function (options) {
return function (css) {
css.walkRules(rule => {
rule.walkAtRules('apply', atRule => {
const mixins = postcss.list.space(atRule.params)
const [customProperties, classes] = _.partition(mixins, mixin => {
return _.startsWith(mixin, '--')
})
const decls = _.flatMap(classes, mixin => {
return findMixin(css, mixin, () => {
throw atRule.error(`No ${mixin} class found.`)
const [customProperties, classes] = _.partition(mixins, mixin => {
return _.startsWith(mixin, '--')
})
const decls = _.flatMap(classes, mixin => {
return findMixin(css, mixin, () => {
throw atRule.error(`No ${mixin} class found.`)
})
})
rule.insertBefore(atRule, decls)
atRule.params = customProperties.join(' ')
if (_.isEmpty(customProperties)) {
atRule.remove()
}
})
rule.insertBefore(atRule, decls)
atRule.params = customProperties.join(' ')
if (_.isEmpty(customProperties)) {
atRule.remove()
}
})
})
}
}

View File

@ -1,23 +1,19 @@
const _ = require('lodash')
const postcss = require('postcss')
const cssnext = require('postcss-cssnext')
const fs = require('fs')
const addCustomMediaQueries = require('./lib/addCustomMediaQueries')
const generateUtilities = require('./lib/generateUtilities')
const substituteClassApplyAtRules = require('./lib/substituteClassApplyAtRules')
module.exports = postcss.plugin('tailwind', function(options) {
return function(css) {
options = options || require('./default-config')
module.exports = postcss.plugin('tailwind', options => {
options = options || require('./default-config')
// const normalize = fs.readFileSync('../node_modules/normalize.css/normalize.css')
// const base = fs.readFileSync('../node_modules/suitcss-base/lib/base.css')
// css.prepend(postcss.parse(base))
// css.prepend(postcss.parse(normalize))
addCustomMediaQueries(css, options)
generateUtilities(css, options)
substituteClassApplyAtRules(css)
}
return postcss([
addCustomMediaQueries(options),
generateUtilities(options),
substituteClassApplyAtRules(options),
require('postcss-cssnext')(),
require('stylefmt'),
])
})