未验证 提交 b931cbec 编写于 作者: J Joe Haddad 提交者: GitHub

Simplify CSS Errors (#12852)

上级 b41f9baa
import Chalk from 'next/dist/compiled/chalk'
import { SimpleWebpackError } from './simpleWebpackError'
const chalk = new Chalk.constructor({ enabled: true })
const regexCssError = /^(?:CssSyntaxError|SyntaxError)\n\n\((\d+):(\d*)\) (.*)$/s
export function getCssError(
fileName: string,
err: Error
): SimpleWebpackError | false {
if (
!(
(err.name === 'CssSyntaxError' || err.name === 'SyntaxError') &&
(err as any).stack === false &&
!(err instanceof SyntaxError)
)
) {
return false
}
// https://github.com/postcss/postcss-loader/blob/d6931da177ac79707bd758436e476036a55e4f59/src/Error.js
const res = regexCssError.exec(err.message)
if (res) {
const [, _lineNumer, _column, reason] = res
const lineNumber = Math.max(1, parseInt(_lineNumer, 10))
const column = Math.max(1, parseInt(_column, 10))
return new SimpleWebpackError(
`${chalk.cyan(fileName)}:${chalk.yellow(
lineNumber.toString()
)}:${chalk.yellow(column.toString())}`,
chalk.red.bold('Syntax error').concat(`: ${reason}`)
)
}
return false
}
......@@ -2,19 +2,23 @@ import * as path from 'path'
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { compilation } from 'webpack'
import { getBabelError } from './parseBabel'
import { getCssError } from './parseCss'
import { SimpleWebpackError } from './simpleWebpackError'
function getFilename(compilation: compilation.Compilation, m: any): string {
let ctx: string | null =
compilation.compiler?.context ?? compilation.context ?? null
if (ctx !== null && typeof m.resource === 'string') {
const res = path.relative(ctx, m.resource).replace(/\\/g, path.posix.sep)
return res.startsWith('.') ? res : `.${path.posix.sep}${res}`
}
const requestShortener = compilation.requestShortener
if (typeof m?.readableIdentifier === 'function') {
return m.readableIdentifier(requestShortener)
}
if (typeof m.resource === 'string') {
const res = path.relative(compilation.context, m.resource)
return res.startsWith('.') ? res : `.${path.sep}${res}`
}
return m.request ?? '<unknown>'
return m.request ?? m.userRequest ?? '<unknown>'
}
export function getModuleBuildError(
......@@ -34,10 +38,16 @@ export function getModuleBuildError(
const err: Error = input.error
const sourceFilename = getFilename(compilation, input.module)
const babel = getBabelError(sourceFilename, err)
if (babel !== false) {
return babel
}
const css = getCssError(sourceFilename, err)
if (css !== false) {
return css
}
return false
}
......@@ -713,3 +713,50 @@ test('conversion to class component (1)', async () => {
await cleanup()
})
test('css syntax errors', async () => {
const [session, cleanup] = await sandbox()
await session.write('index.module.css', `.button {}`)
await session.patch(
'index.js',
`
import './index.module.css';
export default () => {
return (
<div>
<p>lol</p>
</div>
)
}
`
)
expect(await session.hasRedbox()).toBe(false)
// Syntax error
await session.patch('index.module.css', `.button {`)
expect(await session.hasRedbox(true)).toBe(true)
const source = await session.getRedboxSource()
expect(source).toMatchInlineSnapshot(`
"./index.module.css:1:1
Syntax error: Unclosed block
> 1 | .button {
| ^"
`)
// Not local error
await session.patch('index.module.css', `button {}`)
expect(await session.hasRedbox(true)).toBe(true)
const source2 = await session.getRedboxSource()
expect(source2).toMatchInlineSnapshot(`
"./index.module.css:1:1
Syntax error: Selector \\"button\\" is not pure (pure selectors must contain at least one local class or id)
> 1 | button {}
| ^"
`)
await cleanup()
})
......@@ -150,7 +150,7 @@ describe('Custom Properties: Fail for :root {} in CSS Modules', () => {
expect(code).not.toBe(0)
expect(stderr).toContain('Failed to compile')
expect(stderr).toContain('pages/styles.module.css')
expect(stderr).toContain('CssSyntax error: Selector ":root" is not pure')
expect(stderr).toContain('Selector ":root" is not pure')
})
})
......@@ -168,7 +168,7 @@ describe('Custom Properties: Fail for global element in CSS Modules', () => {
expect(code).not.toBe(0)
expect(stderr).toContain('Failed to compile')
expect(stderr).toContain('pages/styles.module.css')
expect(stderr).toContain('CssSyntax error: Selector "h1" is not pure')
expect(stderr).toContain('Selector "h1" is not pure')
})
})
......@@ -218,6 +218,6 @@ describe('CSS Modules: Importing Invalid Global CSS', () => {
expect(code).not.toBe(0)
expect(stderr).toContain('Failed to compile')
expect(stderr).toContain('pages/styles.module.css')
expect(stderr).toContain('CssSyntax error: Selector "a" is not pure')
expect(stderr).toContain('Selector "a" is not pure')
})
})
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册