Nuxt/packages/webpack/src/utils/postcss.ts

93 lines
2.7 KiB
TypeScript
Raw Normal View History

import { createCommonJS } from 'mlly'
import { defaults, merge, cloneDeep } from 'lodash-es'
import { requireModule } from '@nuxt/kit'
import type { Nuxt } from '@nuxt/schema'
2020-07-02 13:02:35 +00:00
const isPureObject = (obj: unknown): obj is Object => obj !== null && !Array.isArray(obj) && typeof obj === 'object'
2020-07-02 13:02:35 +00:00
export const orderPresets = {
cssnanoLast (names: string[]) {
2020-07-02 13:02:35 +00:00
const nanoIndex = names.indexOf('cssnano')
if (nanoIndex !== names.length - 1) {
names.push(names.splice(nanoIndex, 1)[0])
}
return names
},
autoprefixerLast (names: string[]) {
const nanoIndex = names.indexOf('autoprefixer')
2020-07-02 13:02:35 +00:00
if (nanoIndex !== names.length - 1) {
names.push(names.splice(nanoIndex, 1)[0])
}
return names
},
autoprefixerAndCssnanoLast (names: string[]) {
return orderPresets.cssnanoLast(orderPresets.autoprefixerLast(names))
2020-07-02 13:02:35 +00:00
}
}
export const getPostcssConfig = (nuxt: Nuxt) => {
function defaultConfig () {
2020-07-02 13:02:35 +00:00
return {
sourceMap: nuxt.options.webpack.cssSourceMap,
plugins: nuxt.options.postcss.plugins,
2020-07-02 13:02:35 +00:00
// Array, String or Function
order: 'autoprefixerAndCssnanoLast'
2020-07-02 13:02:35 +00:00
}
}
function sortPlugins ({ plugins, order }) {
2020-07-02 13:02:35 +00:00
const names = Object.keys(plugins)
if (typeof order === 'string') {
order = orderPresets[order]
}
return typeof order === 'function' ? order(names, orderPresets) : (order || names)
}
function loadPlugins (config) {
if (!isPureObject(config.plugins)) { return }
// Map postcss plugins into instances on object mode once
const cjs = createCommonJS(import.meta.url)
config.plugins = sortPlugins(config).map((pluginName) => {
const pluginFn = requireModule(pluginName, { paths: [cjs.__dirname] })
const pluginOptions = config.plugins[pluginName]
if (!pluginOptions || typeof pluginFn !== 'function') { return null }
return pluginFn(pluginOptions)
}).filter(Boolean)
2020-07-02 13:02:35 +00:00
}
if (!nuxt.options.webpack.postcss || !nuxt.options.postcss) {
return false
}
2020-07-02 13:02:35 +00:00
const configFile = nuxt.options.postcss?.config
if (configFile) {
return {
postcssOptions: {
config: configFile
},
sourceMap: nuxt.options.webpack.cssSourceMap
2020-07-02 13:02:35 +00:00
}
}
2020-07-02 13:02:35 +00:00
let postcssOptions = cloneDeep(nuxt.options.postcss)
// Apply default plugins
if (isPureObject(postcssOptions)) {
if (Array.isArray(postcssOptions.plugins)) {
defaults(postcssOptions, defaultConfig())
} else {
// Keep the order of default plugins
postcssOptions = merge({}, defaultConfig(), postcssOptions)
loadPlugins(postcssOptions)
}
delete nuxt.options.webpack.postcss.order
return {
sourceMap: nuxt.options.webpack.cssSourceMap,
...nuxt.options.webpack.postcss,
postcssOptions
2020-07-02 13:02:35 +00:00
}
}
}