Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Postcss7 compatibility #2773

Merged
merged 2 commits into from Nov 16, 2020
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion package.json
Expand Up @@ -23,7 +23,10 @@
"rebuild-fixtures": "npm run babelify && babel-node scripts/rebuildFixtures.js",
"prepublishOnly": "npm run babelify && babel-node scripts/build.js",
"style": "eslint .",
"test": "jest && eslint ."
"test": "jest && eslint .",
"precompat": "npm run babelify",
"compat": "node scripts/compat.js --prepare",
"compat:restore": "node scripts/compat.js --restore"
},
"files": [
"dist/*.css",
Expand Down
9 changes: 9 additions & 0 deletions package.postcss7.json
@@ -0,0 +1,9 @@
{
"dependencies": {
"autoprefixer": "^9",
"postcss": "^7",
"postcss-functions": "^3",
"postcss-js": "^2",
"postcss-nested": "^4"
}
}
59 changes: 59 additions & 0 deletions scripts/compat.js
@@ -0,0 +1,59 @@
const fs = require('fs')
const path = require('path')
const merge = require('lodash/merge')

function fromRootPath(...paths) {
return path.resolve(process.cwd(), ...paths)
}

function backupPath(...paths) {
return path.resolve(process.cwd(), 'node_modules', '__tw_cache__', ...paths)
}

function copy(fromPath, toPath) {
fs.mkdirSync(path.dirname(toPath), { recursive: true })
fs.copyFileSync(fromPath, toPath)
}

if (process.argv.includes('--prepare')) {
const mainPackageJson = require('../package.json')
const compatPackageJson = require('../package.postcss7.json')

// 1. Backup original package.json file
copy(fromRootPath('package.json'), backupPath('package.json'))

// 2. Backup lib/index.js file
copy(fromRootPath('lib', 'index.js'), backupPath('lib', 'index.js'))

// 3. Use the postcss7 compat file
copy(fromRootPath('lib', 'index.postcss7.js'), fromRootPath('lib', 'index.js'))

// 4. Deep merge package.json contents
const packageJson = merge({}, mainPackageJson, compatPackageJson)

// 5. Write package.json with the new contents
fs.writeFileSync(fromRootPath('package.json'), JSON.stringify(packageJson, null, 2), 'utf8')

// 6. Print some useful information to make publishing easy
console.log()
console.log('You can safely publish `tailwindcss` in PostCSS 7 compatibility mode:\n')
console.log(
['npm version', 'npm publish --tag compat', 'npm run compat:restore']
.map((v) => ` ${v}`)
.join('\n')
)
console.log()
} else if (process.argv.includes('--restore')) {
// 1. Restore original package.json file
copy(backupPath('package.json'), fromRootPath('package.json'))
fs.unlinkSync(backupPath('package.json'))

// 2. Restore lib/index.js file
copy(backupPath('lib', 'index.js'), fromRootPath('lib', 'index.js'))
fs.unlinkSync(backupPath('lib', 'index.js'))

// 3. Done
console.log()
console.log('Restored from PostCSS 7 mode to latest PostCSS mode!')
console.log()
}
80 changes: 80 additions & 0 deletions src/index.postcss7.js
@@ -0,0 +1,80 @@
import path from 'path'
import fs from 'fs'

import _ from 'lodash'

import getModuleDependencies from './lib/getModuleDependencies'
import registerConfigAsDependency from './lib/registerConfigAsDependency'
import processTailwindFeatures from './processTailwindFeatures'
import formatCSS from './lib/formatCSS'
import resolveConfig from './util/resolveConfig'
import getAllConfigs from './util/getAllConfigs'
import { defaultConfigFile } from './constants'
import defaultConfig from '../stubs/defaultConfig.stub.js'

function resolveConfigPath(filePath) {
// require('tailwindcss')({ theme: ..., variants: ... })
if (_.isObject(filePath) && !_.has(filePath, 'config') && !_.isEmpty(filePath)) {
return undefined
}

// require('tailwindcss')({ config: 'custom-config.js' })
if (_.isObject(filePath) && _.has(filePath, 'config') && _.isString(filePath.config)) {
return path.resolve(filePath.config)
}

// require('tailwindcss')({ config: { theme: ..., variants: ... } })
if (_.isObject(filePath) && _.has(filePath, 'config') && _.isObject(filePath.config)) {
return undefined
}

// require('tailwindcss')('custom-config.js')
if (_.isString(filePath)) {
return path.resolve(filePath)
}

// require('tailwindcss')
try {
const defaultConfigPath = path.resolve(defaultConfigFile)
fs.accessSync(defaultConfigPath)
return defaultConfigPath
} catch (err) {
return undefined
}
}

const getConfigFunction = (config) => () => {
if (_.isUndefined(config)) {
return resolveConfig([...getAllConfigs(defaultConfig)])
}

// Skip this if Jest is running: https://github.com/facebook/jest/pull/9841#issuecomment-621417584
if (process.env.JEST_WORKER_ID === undefined) {
if (!_.isObject(config)) {
getModuleDependencies(config).forEach((mdl) => {
delete require.cache[require.resolve(mdl.file)]
})
}
}

const configObject = _.isObject(config) ? _.get(config, 'config', config) : require(config)

return resolveConfig([...getAllConfigs(configObject)])
}

const plugin = postcss.plugin('tailwind', (config) => {
const plugins = []
const resolvedConfigPath = resolveConfigPath(config)

if (!_.isUndefined(resolvedConfigPath)) {
plugins.push(registerConfigAsDependency(resolvedConfigPath))
}

return postcss([
...plugins,
processTailwindFeatures(getConfigFunction(resolvedConfigPath || config)),
formatCSS,
])
})

module.exports = plugin