Skip to content

Commit aa5530d

Browse files
committed
feat: handle SFC parse error
1 parent a336cf1 commit aa5530d

File tree

3 files changed

+37
-22
lines changed

3 files changed

+37
-22
lines changed

src/formatError.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { generateCodeFrame, CompilerError } from '@vue/compiler-sfc'
2+
import chalk from 'chalk'
3+
4+
export function formatError(err: CompilerError, source: string, file: string) {
5+
if (err.loc) {
6+
const loc = `:${err.loc.start.line}:${err.loc.start.column}`
7+
const filePath = chalk.gray(`at ${file}${loc}`)
8+
const codeframe = generateCodeFrame(
9+
source,
10+
err.loc.start.offset,
11+
err.loc.end.offset
12+
)
13+
err.message = `\n${chalk.red(
14+
`VueCompilerError: ${err.message}`
15+
)}\n${filePath}\n${chalk.yellow(codeframe)}\n`
16+
}
17+
}

src/index.ts

+13-5
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
import { selectBlock } from './select'
2424
import { genHotReloadCode } from './hotReload'
2525
import { genCSSModulesCode } from './cssModules'
26+
import { formatError } from './formatError'
2627

2728
const VueLoaderPlugin = require('./plugin')
2829

@@ -37,7 +38,7 @@ export interface VueLoaderOptions {
3738

3839
let errorEmitted = false
3940

40-
const loader: webpack.loader.Loader = function(source) {
41+
const loader: webpack.loader.Loader = function(source: string) {
4142
const loaderContext = this
4243

4344
// check if plugin is installed
@@ -75,10 +76,17 @@ const loader: webpack.loader.Loader = function(source) {
7576
const isServer = target === 'node'
7677
const isProduction = mode === 'production'
7778

78-
const descriptor = parse(String(source), {
79-
filename: resourcePath,
80-
sourceMap
81-
})
79+
let descriptor
80+
try {
81+
descriptor = parse(source, {
82+
filename: resourcePath,
83+
sourceMap
84+
})
85+
} catch (e) {
86+
formatError(e, source, resourcePath)
87+
loaderContext.emitError(e)
88+
return ``
89+
}
8290

8391
// if the query has a type field, this is a language block request
8492
// e.g. foo.vue?type=template&id=xxxxx

src/templateLoader.ts

+7-17
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import * as webpack from 'webpack'
22
import qs from 'querystring'
3-
import chalk from 'chalk'
43
import loaderUtils from 'loader-utils'
54
import { VueLoaderOptions } from './'
6-
import { compileTemplate, generateCodeFrame } from '@vue/compiler-sfc'
5+
import { formatError } from './formatError'
6+
import { compileTemplate } from '@vue/compiler-sfc'
77

88
// Loader that compiles raw template into JavaScript functions.
99
// This is injected by the global pitcher (../pitch) for template
@@ -48,21 +48,11 @@ const TemplateLoader: webpack.loader.Loader = function(source, inMap) {
4848
if (typeof err === 'string') {
4949
loaderContext.emitError(err)
5050
} else {
51-
if (err.loc) {
52-
const loc = `:${err.loc.start.line}:${err.loc.start.column}`
53-
const filePath = chalk.gray(`at ${loaderContext.resourcePath}${loc}`)
54-
const originalSource = inMap
55-
? inMap.sourcesContent![0]
56-
: (source as string)
57-
const codeframe = generateCodeFrame(
58-
originalSource,
59-
err.loc.start.offset,
60-
err.loc.end.offset
61-
)
62-
err.message = `\n${chalk.red(
63-
`Syntax Error: ${err.message}`
64-
)}\n${filePath}\n${chalk.yellow(codeframe)}\n`
65-
}
51+
formatError(
52+
err,
53+
inMap ? inMap.sourcesContent![0] : (source as string),
54+
loaderContext.resourcePath
55+
)
6656
loaderContext.emitError(err)
6757
}
6858
})

0 commit comments

Comments
 (0)