Redesign PostCSS Configuration Loading (#9704)
* Redesign PostCSS Configuration Loading * Test array configuration * Test new configuration handling * Remove unnecessary async
This commit is contained in:
parent
a6dc0e1603
commit
179e627a36
36 changed files with 651 additions and 67 deletions
|
@ -75,6 +75,8 @@
|
|||
"node-notifier": "5.4.0",
|
||||
"node-sass": "4.12.0",
|
||||
"npm-run-all": "4.1.5",
|
||||
"pixrem": "5.0.0",
|
||||
"postcss-pseudoelements": "5.0.0",
|
||||
"postcss-short-size": "4.0.0",
|
||||
"postcss-trolling": "0.1.7",
|
||||
"pre-commit": "1.2.2",
|
||||
|
|
|
@ -2,36 +2,79 @@ import chalk from 'chalk'
|
|||
import { findConfig } from '../../../../../lib/find-config'
|
||||
import { resolveRequest } from '../../../../../lib/resolve-request'
|
||||
|
||||
export async function getPostCssPlugins(dir: string): Promise<unknown[]> {
|
||||
function load(plugins: { [key: string]: object | false }): unknown[] {
|
||||
return Object.keys(plugins)
|
||||
.map(pkg => {
|
||||
const options = plugins[pkg]
|
||||
if (options === false) {
|
||||
return false
|
||||
}
|
||||
type CssPluginCollection_Array = (string | [string, boolean | object])[]
|
||||
|
||||
const pluginPath = resolveRequest(pkg, `${dir}/`)
|
||||
type CssPluginCollection_Object = { [key: string]: object | boolean }
|
||||
|
||||
if (options == null || Object.keys(options).length === 0) {
|
||||
return require(pluginPath)
|
||||
}
|
||||
return require(pluginPath)(options)
|
||||
})
|
||||
.filter(Boolean)
|
||||
type CssPluginCollection =
|
||||
| CssPluginCollection_Array
|
||||
| CssPluginCollection_Object
|
||||
|
||||
type CssPluginShape = [string, object | boolean]
|
||||
|
||||
const genericErrorText = 'Malformed PostCSS Configuration'
|
||||
|
||||
function getError_NullConfig(pluginName: string) {
|
||||
return `${chalk.red.bold(
|
||||
'Error'
|
||||
)}: Your PostCSS configuration for '${pluginName}' cannot have ${chalk.bold(
|
||||
'null'
|
||||
)} configuration.\nTo disable '${pluginName}', pass ${chalk.bold(
|
||||
'false'
|
||||
)}, otherwise, pass ${chalk.bold('true')} or a configuration object.`
|
||||
}
|
||||
|
||||
function isIgnoredPlugin(pluginPath: string): boolean {
|
||||
const ignoredRegex = /(?:^|[\\/])(postcss-modules-values|postcss-modules-scope|postcss-modules-extract-imports|postcss-modules-local-by-default|postcss-modules)(?:[\\/]|$)/i
|
||||
const match = ignoredRegex.exec(pluginPath)
|
||||
if (match == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
const config = await findConfig<{ plugins: { [key: string]: object } }>(
|
||||
dir,
|
||||
'postcss'
|
||||
const plugin = match.pop()!
|
||||
console.warn(
|
||||
`${chalk.yellow.bold('Warning')}: Please remove the ${chalk.underline(
|
||||
plugin
|
||||
)} plugin from your PostCSS configuration. ` +
|
||||
`This plugin is automatically configured by Next.js.`
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
let target: unknown[]
|
||||
async function loadPlugin(
|
||||
dir: string,
|
||||
pluginName: string,
|
||||
options: boolean | object
|
||||
): Promise<import('postcss').AcceptedPlugin | false> {
|
||||
if (options === false || isIgnoredPlugin(pluginName)) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (!config) {
|
||||
target = load({
|
||||
[require.resolve('postcss-flexbugs-fixes')]: {},
|
||||
[require.resolve('postcss-preset-env')]: {
|
||||
if (options == null) {
|
||||
console.error(getError_NullConfig(pluginName))
|
||||
throw new Error(genericErrorText)
|
||||
}
|
||||
|
||||
const pluginPath = resolveRequest(pluginName, `${dir}/`)
|
||||
if (isIgnoredPlugin(pluginPath)) {
|
||||
return false
|
||||
} else if (options === true) {
|
||||
return require(pluginPath)
|
||||
} else {
|
||||
const keys = Object.keys(options)
|
||||
if (keys.length === 0) {
|
||||
return require(pluginPath)
|
||||
}
|
||||
return require(pluginPath)(options)
|
||||
}
|
||||
}
|
||||
|
||||
function getDefaultPlugins(): CssPluginCollection {
|
||||
return [
|
||||
require.resolve('postcss-flexbugs-fixes'),
|
||||
[
|
||||
require.resolve('postcss-preset-env'),
|
||||
{
|
||||
autoprefixer: {
|
||||
// Disable legacy flexbox support
|
||||
flexbox: 'no-2009',
|
||||
|
@ -40,49 +83,109 @@ export async function getPostCssPlugins(dir: string): Promise<unknown[]> {
|
|||
// web platform, i.e. in 2+ browsers unflagged.
|
||||
stage: 3,
|
||||
},
|
||||
})
|
||||
} else {
|
||||
const plugins = config.plugins
|
||||
if (plugins == null || typeof plugins !== 'object') {
|
||||
throw new Error(
|
||||
`Your custom PostCSS configuration must export a \`plugins\` key.`
|
||||
)
|
||||
}
|
||||
],
|
||||
]
|
||||
}
|
||||
|
||||
const invalidKey = Object.keys(config).find(key => key !== 'plugins')
|
||||
if (invalidKey) {
|
||||
console.warn(
|
||||
`${chalk.yellow.bold(
|
||||
'Warning'
|
||||
)}: Your PostCSS configuration defines a field which is not supported (\`${invalidKey}\`). ` +
|
||||
`Please remove this configuration value.`
|
||||
)
|
||||
}
|
||||
export async function getPostCssPlugins(
|
||||
dir: string
|
||||
): Promise<import('postcss').AcceptedPlugin[]> {
|
||||
let config = await findConfig<{ plugins: CssPluginCollection }>(
|
||||
dir,
|
||||
'postcss'
|
||||
)
|
||||
|
||||
// These plugins cannot be enabled by the user because they'll conflict with
|
||||
// `css-loader`'s behavior to make us compatible with webpack.
|
||||
;[
|
||||
'postcss-modules-values',
|
||||
'postcss-modules-scope',
|
||||
'postcss-modules-extract-imports',
|
||||
'postcss-modules-local-by-default',
|
||||
'postcss-modules',
|
||||
].forEach(plugin => {
|
||||
if (!plugins.hasOwnProperty(plugin)) {
|
||||
return
|
||||
}
|
||||
|
||||
console.warn(
|
||||
`${chalk.yellow.bold('Warning')}: Please remove the ${chalk.underline(
|
||||
plugin
|
||||
)} plugin from your PostCSS configuration. ` +
|
||||
`This plugin is automatically configured by Next.js.`
|
||||
)
|
||||
delete plugins[plugin]
|
||||
})
|
||||
|
||||
target = load(plugins as { [key: string]: object })
|
||||
if (config == null) {
|
||||
config = { plugins: getDefaultPlugins() }
|
||||
}
|
||||
|
||||
return target
|
||||
// Warn user about configuration keys which are not respected
|
||||
const invalidKey = Object.keys(config).find(key => key !== 'plugins')
|
||||
if (invalidKey) {
|
||||
console.warn(
|
||||
`${chalk.yellow.bold(
|
||||
'Warning'
|
||||
)}: Your PostCSS configuration defines a field which is not supported (\`${invalidKey}\`). ` +
|
||||
`Please remove this configuration value.`
|
||||
)
|
||||
}
|
||||
|
||||
// Enforce the user provided plugins if the configuration file is present
|
||||
let plugins = config.plugins
|
||||
if (plugins == null || typeof plugins !== 'object') {
|
||||
throw new Error(
|
||||
`Your custom PostCSS configuration must export a \`plugins\` key.`
|
||||
)
|
||||
}
|
||||
|
||||
if (!Array.isArray(plugins)) {
|
||||
// Capture variable so TypeScript is happy
|
||||
const pc = plugins
|
||||
|
||||
plugins = Object.keys(plugins).reduce((acc, curr) => {
|
||||
const p = pc[curr]
|
||||
if (typeof p === 'undefined') {
|
||||
console.error(getError_NullConfig(curr))
|
||||
throw new Error(genericErrorText)
|
||||
}
|
||||
|
||||
acc.push([curr, p])
|
||||
return acc
|
||||
}, [] as CssPluginCollection_Array)
|
||||
}
|
||||
|
||||
const parsed: CssPluginShape[] = []
|
||||
plugins.forEach(plugin => {
|
||||
if (plugin == null) {
|
||||
console.warn(
|
||||
`${chalk.yellow.bold('Warning')}: A ${chalk.bold(
|
||||
'null'
|
||||
)} PostCSS plugin was provided. This entry will be ignored.`
|
||||
)
|
||||
} else if (typeof plugin === 'string') {
|
||||
parsed.push([plugin, true])
|
||||
} else if (Array.isArray(plugin)) {
|
||||
const pluginName = plugin[0]
|
||||
const pluginConfig = plugin[1]
|
||||
if (
|
||||
typeof pluginName === 'string' &&
|
||||
(typeof pluginConfig === 'boolean' || typeof pluginConfig === 'object')
|
||||
) {
|
||||
parsed.push([pluginName, pluginConfig])
|
||||
} else {
|
||||
if (typeof pluginName !== 'string') {
|
||||
console.error(
|
||||
`${chalk.red.bold(
|
||||
'Error'
|
||||
)}: A PostCSS Plugin must be provided as a ${chalk.bold(
|
||||
'string'
|
||||
)}. Instead, we got: '${pluginName}'.`
|
||||
)
|
||||
} else {
|
||||
console.error(
|
||||
`${chalk.red.bold(
|
||||
'Error'
|
||||
)}: A PostCSS Plugin was passed as an array but did not provide its configuration ('${pluginName}').`
|
||||
)
|
||||
}
|
||||
throw new Error(genericErrorText)
|
||||
}
|
||||
} else {
|
||||
console.error(
|
||||
`${chalk.red.bold(
|
||||
'Error'
|
||||
)}: An unknown PostCSS plugin was provided (${plugin}).`
|
||||
)
|
||||
throw new Error(genericErrorText)
|
||||
}
|
||||
})
|
||||
|
||||
const resolved = await Promise.all(
|
||||
parsed.map(p => loadPlugin(dir, p[0], p[1]))
|
||||
)
|
||||
const filtered: import('postcss').AcceptedPlugin[] = resolved.filter(
|
||||
Boolean
|
||||
) as import('postcss').AcceptedPlugin[]
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"plugins": [["postcss-trolling"]]
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import React from 'react'
|
||||
import App from 'next/app'
|
||||
import '../styles/global.css'
|
||||
|
||||
class MyApp extends App {
|
||||
render() {
|
||||
const { Component, pageProps } = this.props
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
}
|
||||
|
||||
export default MyApp
|
|
@ -0,0 +1,3 @@
|
|||
export default function Home() {
|
||||
return <div />
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/* this should pass through untransformed */
|
||||
@media (480px <= width < 768px) {
|
||||
a::before {
|
||||
content: '';
|
||||
}
|
||||
::placeholder {
|
||||
color: green;
|
||||
}
|
||||
}
|
||||
|
||||
/* this should be transformed to width/height */
|
||||
.video {
|
||||
-xyz-max-size: 400rem 300rem;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"plugins": [["postcss-trolling", null]]
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import React from 'react'
|
||||
import App from 'next/app'
|
||||
import '../styles/global.css'
|
||||
|
||||
class MyApp extends App {
|
||||
render() {
|
||||
const { Component, pageProps } = this.props
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
}
|
||||
|
||||
export default MyApp
|
|
@ -0,0 +1,3 @@
|
|||
export default function Home() {
|
||||
return <div />
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/* this should pass through untransformed */
|
||||
@media (480px <= width < 768px) {
|
||||
a::before {
|
||||
content: '';
|
||||
}
|
||||
::placeholder {
|
||||
color: green;
|
||||
}
|
||||
}
|
||||
|
||||
/* this should be transformed to width/height */
|
||||
.video {
|
||||
-xyz-max-size: 400rem 300rem;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"plugins": [[5, null]]
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import React from 'react'
|
||||
import App from 'next/app'
|
||||
import '../styles/global.css'
|
||||
|
||||
class MyApp extends App {
|
||||
render() {
|
||||
const { Component, pageProps } = this.props
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
}
|
||||
|
||||
export default MyApp
|
|
@ -0,0 +1,3 @@
|
|||
export default function Home() {
|
||||
return <div />
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/* this should pass through untransformed */
|
||||
@media (480px <= width < 768px) {
|
||||
a::before {
|
||||
content: '';
|
||||
}
|
||||
::placeholder {
|
||||
color: green;
|
||||
}
|
||||
}
|
||||
|
||||
/* this should be transformed to width/height */
|
||||
.video {
|
||||
-xyz-max-size: 400rem 300rem;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"plugins": [5]
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import React from 'react'
|
||||
import App from 'next/app'
|
||||
import '../styles/global.css'
|
||||
|
||||
class MyApp extends App {
|
||||
render() {
|
||||
const { Component, pageProps } = this.props
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
}
|
||||
|
||||
export default MyApp
|
|
@ -0,0 +1,3 @@
|
|||
export default function Home() {
|
||||
return <div />
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/* this should pass through untransformed */
|
||||
@media (480px <= width < 768px) {
|
||||
a::before {
|
||||
content: '';
|
||||
}
|
||||
::placeholder {
|
||||
color: green;
|
||||
}
|
||||
}
|
||||
|
||||
/* this should be transformed to width/height */
|
||||
.video {
|
||||
-xyz-max-size: 400rem 300rem;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"plugins": null
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import React from 'react'
|
||||
import App from 'next/app'
|
||||
import '../styles/global.css'
|
||||
|
||||
class MyApp extends App {
|
||||
render() {
|
||||
const { Component, pageProps } = this.props
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
}
|
||||
|
||||
export default MyApp
|
|
@ -0,0 +1,3 @@
|
|||
export default function Home() {
|
||||
return <div />
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/* this should pass through untransformed */
|
||||
@media (480px <= width < 768px) {
|
||||
a::before {
|
||||
content: '';
|
||||
}
|
||||
::placeholder {
|
||||
color: green;
|
||||
}
|
||||
}
|
||||
|
||||
/* this should be transformed to width/height */
|
||||
.video {
|
||||
-xyz-max-size: 400rem 300rem;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -0,0 +1,12 @@
|
|||
import React from 'react'
|
||||
import App from 'next/app'
|
||||
import '../styles/global.css'
|
||||
|
||||
class MyApp extends App {
|
||||
render() {
|
||||
const { Component, pageProps } = this.props
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
}
|
||||
|
||||
export default MyApp
|
|
@ -0,0 +1,3 @@
|
|||
export default function Home() {
|
||||
return <div />
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/* this should pass through untransformed */
|
||||
@media (480px <= width < 768px) {
|
||||
a::before {
|
||||
content: '';
|
||||
}
|
||||
::placeholder {
|
||||
color: green;
|
||||
}
|
||||
}
|
||||
|
||||
/* this should be transformed to width/height */
|
||||
.video {
|
||||
-xyz-max-size: 400rem 300rem;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"plugins": [["postcss-trolling", 5]]
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import React from 'react'
|
||||
import App from 'next/app'
|
||||
import '../styles/global.css'
|
||||
|
||||
class MyApp extends App {
|
||||
render() {
|
||||
const { Component, pageProps } = this.props
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
}
|
||||
|
||||
export default MyApp
|
|
@ -0,0 +1,3 @@
|
|||
export default function Home() {
|
||||
return <div />
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/* this should pass through untransformed */
|
||||
@media (480px <= width < 768px) {
|
||||
a::before {
|
||||
content: '';
|
||||
}
|
||||
::placeholder {
|
||||
color: green;
|
||||
}
|
||||
}
|
||||
|
||||
/* this should be transformed to width/height */
|
||||
.video {
|
||||
-xyz-max-size: 400rem 300rem;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
// Use comments to test JSON5 support
|
||||
"plugins": [
|
||||
"pixrem",
|
||||
["postcss-pseudoelements", true],
|
||||
// Test a non-standard feature that wouldn't be normally enabled
|
||||
[
|
||||
"postcss-short-size",
|
||||
{
|
||||
// Add a prefix to test that configuration is passed
|
||||
"prefix": "xyz"
|
||||
}
|
||||
],
|
||||
["postcss-trolling", false]
|
||||
]
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import React from 'react'
|
||||
import App from 'next/app'
|
||||
import '../styles/global.css'
|
||||
|
||||
class MyApp extends App {
|
||||
render() {
|
||||
const { Component, pageProps } = this.props
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
}
|
||||
|
||||
export default MyApp
|
|
@ -0,0 +1,3 @@
|
|||
export default function Home() {
|
||||
return <div />
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/* this should pass through untransformed */
|
||||
@media (480px <= width < 768px) {
|
||||
a::before {
|
||||
content: '';
|
||||
}
|
||||
::placeholder {
|
||||
color: green;
|
||||
}
|
||||
}
|
||||
|
||||
/* this should be transformed to width/height */
|
||||
.video {
|
||||
-xyz-max-size: 400rem 300rem;
|
||||
}
|
|
@ -283,6 +283,73 @@ describe('CSS Support', () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('CSS Customization Array', () => {
|
||||
const appDir = join(fixturesDir, 'custom-configuration-arr')
|
||||
|
||||
beforeAll(async () => {
|
||||
await remove(join(appDir, '.next'))
|
||||
})
|
||||
|
||||
it('should build successfully', async () => {
|
||||
await nextBuild(appDir)
|
||||
})
|
||||
|
||||
it(`should've compiled and prefixed`, async () => {
|
||||
const cssFolder = join(appDir, '.next/static/css')
|
||||
|
||||
const files = await readdir(cssFolder)
|
||||
const cssFiles = files.filter(f => /\.css$/.test(f))
|
||||
|
||||
expect(cssFiles.length).toBe(1)
|
||||
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
|
||||
expect(
|
||||
cssContent.replace(/\/\*.*?\*\//g, '').trim()
|
||||
).toMatchInlineSnapshot(
|
||||
`"@media (480px <= width < 768px){a:before{content:\\"\\"}::placeholder{color:green}}.video{max-width:6400px;max-height:4800px;max-width:400rem;max-height:300rem}"`
|
||||
)
|
||||
|
||||
// Contains a source map
|
||||
expect(cssContent).toMatch(/\/\*#\s*sourceMappingURL=(.+\.map)\s*\*\//)
|
||||
})
|
||||
|
||||
it(`should've emitted a source map`, async () => {
|
||||
const cssFolder = join(appDir, '.next/static/css')
|
||||
|
||||
const files = await readdir(cssFolder)
|
||||
const cssMapFiles = files.filter(f => /\.css\.map$/.test(f))
|
||||
|
||||
expect(cssMapFiles.length).toBe(1)
|
||||
const cssMapContent = (
|
||||
await readFile(join(cssFolder, cssMapFiles[0]), 'utf8')
|
||||
).trim()
|
||||
|
||||
const { version, mappings, sourcesContent } = JSON.parse(cssMapContent)
|
||||
expect({ version, mappings, sourcesContent }).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"mappings": "AACA,gCACE,SACE,UACF,CACA,cACE,WACF,CACF,CAGA,OACE,gBAA4B,CAA5B,iBAA4B,CAA5B,gBAA4B,CAA5B,iBACF",
|
||||
"sourcesContent": Array [
|
||||
"/* this should pass through untransformed */
|
||||
@media (480px <= width < 768px) {
|
||||
a::before {
|
||||
content: '';
|
||||
}
|
||||
::placeholder {
|
||||
color: green;
|
||||
}
|
||||
}
|
||||
|
||||
/* this should be transformed to width/height */
|
||||
.video {
|
||||
-xyz-max-size: 400rem 300rem;
|
||||
}
|
||||
",
|
||||
],
|
||||
"version": 3,
|
||||
}
|
||||
`)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Bad CSS Customization', () => {
|
||||
const appDir = join(fixturesDir, 'bad-custom-configuration')
|
||||
|
||||
|
@ -333,6 +400,126 @@ describe('CSS Support', () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('Bad CSS Customization Array (1)', () => {
|
||||
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-1')
|
||||
|
||||
beforeAll(async () => {
|
||||
await remove(join(appDir, '.next'))
|
||||
})
|
||||
|
||||
it('should fail the build', async () => {
|
||||
const { stderr } = await nextBuild(appDir, [], { stderr: true })
|
||||
|
||||
expect(stderr).toMatch(
|
||||
/A PostCSS Plugin was passed as an array but did not provide its configuration \('postcss-trolling'\)/
|
||||
)
|
||||
expect(stderr).toMatch(/Build error occurred/)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Bad CSS Customization Array (2)', () => {
|
||||
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-2')
|
||||
|
||||
beforeAll(async () => {
|
||||
await remove(join(appDir, '.next'))
|
||||
})
|
||||
|
||||
it('should fail the build', async () => {
|
||||
const { stderr } = await nextBuild(appDir, [], { stderr: true })
|
||||
|
||||
expect(stderr).toMatch(
|
||||
/Error: Your PostCSS configuration for 'postcss-trolling' cannot have null configuration./
|
||||
)
|
||||
expect(stderr).toMatch(
|
||||
/To disable 'postcss-trolling', pass false, otherwise, pass true or a configuration object./
|
||||
)
|
||||
expect(stderr).toMatch(/Build error occurred/)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Bad CSS Customization Array (3)', () => {
|
||||
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-3')
|
||||
|
||||
beforeAll(async () => {
|
||||
await remove(join(appDir, '.next'))
|
||||
})
|
||||
|
||||
it('should fail the build', async () => {
|
||||
const { stderr } = await nextBuild(appDir, [], { stderr: true })
|
||||
|
||||
expect(stderr).toMatch(
|
||||
/A PostCSS Plugin must be provided as a string. Instead, we got: '5'/
|
||||
)
|
||||
expect(stderr).toMatch(/Build error occurred/)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Bad CSS Customization Array (4)', () => {
|
||||
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-4')
|
||||
|
||||
beforeAll(async () => {
|
||||
await remove(join(appDir, '.next'))
|
||||
})
|
||||
|
||||
it('should fail the build', async () => {
|
||||
const { stderr } = await nextBuild(appDir, [], { stderr: true })
|
||||
|
||||
expect(stderr).toMatch(/An unknown PostCSS plugin was provided \(5\)/)
|
||||
expect(stderr).toMatch(/Build error occurred/)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Bad CSS Customization Array (5)', () => {
|
||||
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-5')
|
||||
|
||||
beforeAll(async () => {
|
||||
await remove(join(appDir, '.next'))
|
||||
})
|
||||
|
||||
it('should fail the build', async () => {
|
||||
const { stderr } = await nextBuild(appDir, [], { stderr: true })
|
||||
|
||||
expect(stderr).toMatch(
|
||||
/Your custom PostCSS configuration must export a `plugins` key./
|
||||
)
|
||||
expect(stderr).toMatch(/Build error occurred/)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Bad CSS Customization Array (6)', () => {
|
||||
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-6')
|
||||
|
||||
beforeAll(async () => {
|
||||
await remove(join(appDir, '.next'))
|
||||
})
|
||||
|
||||
it('should fail the build', async () => {
|
||||
const { stderr } = await nextBuild(appDir, [], { stderr: true })
|
||||
|
||||
expect(stderr).toMatch(
|
||||
/Your custom PostCSS configuration must export a `plugins` key./
|
||||
)
|
||||
expect(stderr).toMatch(/Build error occurred/)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Bad CSS Customization Array (7)', () => {
|
||||
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-7')
|
||||
|
||||
beforeAll(async () => {
|
||||
await remove(join(appDir, '.next'))
|
||||
})
|
||||
|
||||
it('should fail the build', async () => {
|
||||
const { stderr } = await nextBuild(appDir, [], { stderr: true })
|
||||
|
||||
expect(stderr).toMatch(
|
||||
/A PostCSS Plugin was passed as an array but did not provide its configuration \('postcss-trolling'\)/
|
||||
)
|
||||
expect(stderr).toMatch(/Build error occurred/)
|
||||
})
|
||||
})
|
||||
|
||||
// Tests css ordering
|
||||
describe('Multi Global Support (reversed)', () => {
|
||||
const appDir = join(fixturesDir, 'multi-global-reversed')
|
||||
|
|
31
yarn.lock
31
yarn.lock
|
@ -4164,7 +4164,7 @@ browserify-zlib@^0.2.0:
|
|||
dependencies:
|
||||
pako "~1.0.5"
|
||||
|
||||
browserslist@^4.0.0, browserslist@^4.6.0, browserslist@^4.6.3, browserslist@^4.6.4, browserslist@^4.7.1, browserslist@^4.7.3:
|
||||
browserslist@^4.0.0, browserslist@^4.3.6, browserslist@^4.6.0, browserslist@^4.6.3, browserslist@^4.6.4, browserslist@^4.7.1, browserslist@^4.7.3:
|
||||
version "4.8.2"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.2.tgz#b45720ad5fbc8713b7253c20766f701c9a694289"
|
||||
integrity sha512-+M4oeaTplPm/f1pXDw84YohEv7B1i/2Aisei8s4s6k3QsoSHa7i5sz8u/cGQkkatCPxMASKxPualR4wwYgVboA==
|
||||
|
@ -11792,6 +11792,15 @@ pirates@^4.0.1:
|
|||
dependencies:
|
||||
node-modules-regexp "^1.0.0"
|
||||
|
||||
pixrem@5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pixrem/-/pixrem-5.0.0.tgz#460c534fbc19e4e9fbf39012ae26c7107cd40bca"
|
||||
integrity sha512-ugJ4Imy92u55zeznaN/5d7iqOBIZjZ7q10/T+dcd0IuFtbLlsGDvAUabFu1cafER+G9f0T1WtTqvzm4KAdcDgQ==
|
||||
dependencies:
|
||||
browserslist "^4.3.6"
|
||||
postcss "^7.0.7"
|
||||
reduce-css-calc "^2.1.5"
|
||||
|
||||
pkg-dir@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
|
||||
|
@ -12415,6 +12424,13 @@ postcss-pseudo-class-any-link@^6.0.0:
|
|||
postcss "^7.0.2"
|
||||
postcss-selector-parser "^5.0.0-rc.3"
|
||||
|
||||
postcss-pseudoelements@5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-pseudoelements/-/postcss-pseudoelements-5.0.0.tgz#eef194e8d524645ca520a949e95e518e812402cb"
|
||||
integrity sha1-7vGU6NUkZFylIKlJ6V5RjoEkAss=
|
||||
dependencies:
|
||||
postcss "^6.0.0"
|
||||
|
||||
postcss-reduce-initial@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df"
|
||||
|
@ -12548,7 +12564,7 @@ postcss@^5.0.10:
|
|||
source-map "^0.5.6"
|
||||
supports-color "^3.2.3"
|
||||
|
||||
postcss@^6.0.1, postcss@^6.0.23, postcss@^6.0.9:
|
||||
postcss@^6.0.0, postcss@^6.0.1, postcss@^6.0.23, postcss@^6.0.9:
|
||||
version "6.0.23"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324"
|
||||
integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==
|
||||
|
@ -12584,6 +12600,15 @@ postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.17, postcss@^7.0.18, postcss@^7.0
|
|||
source-map "^0.6.1"
|
||||
supports-color "^6.1.0"
|
||||
|
||||
postcss@^7.0.7:
|
||||
version "7.0.24"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.24.tgz#972c3c5be431b32e40caefe6c81b5a19117704c2"
|
||||
integrity sha512-Xl0XvdNWg+CblAXzNvbSOUvgJXwSjmbAKORqyw9V2AlHrm1js2gFw9y3jibBAhpKZi8b5JzJCVh/FyzPsTtgTA==
|
||||
dependencies:
|
||||
chalk "^2.4.2"
|
||||
source-map "^0.6.1"
|
||||
supports-color "^6.1.0"
|
||||
|
||||
pre-commit@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/pre-commit/-/pre-commit-1.2.2.tgz#dbcee0ee9de7235e57f79c56d7ce94641a69eec6"
|
||||
|
@ -13155,7 +13180,7 @@ redent@^2.0.0:
|
|||
indent-string "^3.0.0"
|
||||
strip-indent "^2.0.0"
|
||||
|
||||
reduce-css-calc@^2.1.6:
|
||||
reduce-css-calc@^2.1.5, reduce-css-calc@^2.1.6:
|
||||
version "2.1.7"
|
||||
resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-2.1.7.tgz#1ace2e02c286d78abcd01fd92bfe8097ab0602c2"
|
||||
integrity sha512-fDnlZ+AybAS3C7Q9xDq5y8A2z+lT63zLbynew/lur/IR24OQF5x98tfNwf79mzEdfywZ0a2wpM860FhFfMxZlA==
|
||||
|
|
Loading…
Reference in a new issue