Skip to content

Commit 201cc62

Browse files
committed
feat: handle line offset in errors
1 parent 07a03bd commit 201cc62

File tree

4 files changed

+81
-26
lines changed

4 files changed

+81
-26
lines changed

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
"@vue/compiler-sfc": "^3.0.0-alpha.0"
1818
},
1919
"dependencies": {
20+
"chalk": "^3.0.0",
2021
"hash-sum": "^2.0.0",
21-
"loader-utils": "^1.2.3"
22+
"loader-utils": "^1.2.3",
23+
"source-map": "^0.6.1"
2224
},
2325
"devDependencies": {
2426
"@types/hash-sum": "^1.0.0",

src/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ import {
88
TemplateCompiler,
99
CompilerOptions,
1010
SFCBlock,
11-
TemplateCompileOptions
11+
SFCTemplateCompileOptions
1212
} from '@vue/compiler-sfc'
1313
import { selectBlock } from './select'
1414
import { genHotReloadCode } from './hotReload'
1515

1616
const VueLoaderPlugin = require('./plugin')
1717

1818
export interface VueLoaderOptions {
19-
transformAssetUrls?: TemplateCompileOptions['transformAssetUrls']
19+
transformAssetUrls?: SFCTemplateCompileOptions['transformAssetUrls']
2020
compiler?: TemplateCompiler
2121
compilerOptions?: CompilerOptions
2222
hotReload?: boolean

src/templateLoader.ts

+31-23
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,37 @@
11
import * as webpack from 'webpack'
22
import qs from 'querystring'
3+
import chalk from 'chalk'
34
import loaderUtils from 'loader-utils'
45
import { VueLoaderOptions } from './'
5-
import {
6-
compileTemplate,
7-
TemplateCompileOptions,
8-
generateCodeFrame
9-
} from '@vue/compiler-sfc'
6+
import { SourceMapConsumer, RawSourceMap } from 'source-map'
7+
import { compileTemplate, generateCodeFrame } from '@vue/compiler-sfc'
108

119
// Loader that compiles raw template into JavaScript functions.
1210
// This is injected by the global pitcher (../pitch) for template
1311
// selection requests initiated from vue files.
14-
const TemplateLoader: webpack.loader.Loader = function(source) {
12+
const TemplateLoader: webpack.loader.Loader = function(source, inMap) {
1513
source = String(source)
1614
const loaderContext = this
17-
const query = qs.parse(this.resourceQuery.slice(1))
1815

1916
// although this is not the main vue-loader, we can get access to the same
2017
// vue-loader options because we've set an ident in the plugin and used that
2118
// ident to create the request for this loader in the pitcher.
2219
const options = (loaderUtils.getOptions(loaderContext) ||
2320
{}) as VueLoaderOptions
24-
const { id } = query
21+
2522
// const isServer = loaderContext.target === 'node'
2623
// const isProduction = options.productionMode || loaderContext.minimize || process.env.NODE_ENV === 'production'
24+
const query = qs.parse(this.resourceQuery.slice(1))
25+
const scopedId = query.scoped ? `data-v-${query.id}` : null
26+
scopedId // TODO this is for SSR
2727

28-
const compilerOptions = Object.assign({}, options.compilerOptions, {
29-
// TODO line offset
30-
scopeId: query.scoped ? `data-v-${id}` : null
31-
})
32-
33-
// for vue-component-compiler
34-
const finalOptions: TemplateCompileOptions = {
28+
const compiled = compileTemplate({
3529
source,
3630
filename: this.resourcePath,
3731
compiler: options.compiler,
38-
compilerOptions,
32+
compilerOptions: options.compilerOptions,
3933
transformAssetUrls: options.transformAssetUrls || true
40-
}
41-
42-
const compiled = compileTemplate(finalOptions)
34+
})
4335

4436
// tips
4537
if (compiled.tips.length) {
@@ -50,17 +42,24 @@ const TemplateLoader: webpack.loader.Loader = function(source) {
5042

5143
// errors
5244
if (compiled.errors && compiled.errors.length) {
45+
const lineOffset = inMap ? getLineOffset(inMap) : 0
5346
compiled.errors.forEach(err => {
5447
if (typeof err === 'string') {
5548
loaderContext.emitError(err)
5649
} else {
5750
if (err.loc) {
58-
err.message = `\n${err.message}\n\n${
59-
generateCodeFrame(
51+
const filePath = chalk.blueBright(`${
52+
loaderContext.resourcePath
53+
}:${err.loc.start.line}:${err.loc.start.column}`)
54+
err.message = `\n${filePath}\n${
55+
chalk.red(err.message.replace(/\s+\(\d+:\d+\)/, ''))
56+
}\n${
57+
chalk.yellow(generateCodeFrame(
6058
source as string,
6159
err.loc.start.offset,
62-
err.loc.end.offset
63-
)}`
60+
err.loc.end.offset,
61+
lineOffset
62+
))}\n`
6463
}
6564
loaderContext.emitError(err)
6665
}
@@ -71,4 +70,13 @@ const TemplateLoader: webpack.loader.Loader = function(source) {
7170
loaderContext.callback(null, code, map as any)
7271
}
7372

73+
function getLineOffset(map: RawSourceMap): number {
74+
const consumer = new SourceMapConsumer(map)
75+
let offset = 0
76+
consumer.eachMapping(map => {
77+
offset = map.originalLine - map.generatedLine
78+
})
79+
return offset
80+
}
81+
7482
module.exports = TemplateLoader

yarn.lock

+45
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a"
88
integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==
99

10+
"@types/color-name@^1.1.1":
11+
version "1.1.1"
12+
resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
13+
integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==
14+
1015
"@types/events@*":
1116
version "3.0.0"
1217
resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
@@ -308,6 +313,14 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1:
308313
dependencies:
309314
color-convert "^1.9.0"
310315

316+
ansi-styles@^4.1.0:
317+
version "4.2.0"
318+
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.0.tgz#5681f0dcf7ae5880a7841d8831c4724ed9cc0172"
319+
integrity sha512-7kFQgnEaMdRtwf6uSfUnVr9gSGC7faurn+J/Mv90/W+iTtN0405/nLdopfMWwchyxhbGYl6TC4Sccn9TUkGAgg==
320+
dependencies:
321+
"@types/color-name" "^1.1.1"
322+
color-convert "^2.0.1"
323+
311324
anymatch@^2.0.0:
312325
version "2.0.0"
313326
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb"
@@ -668,6 +681,14 @@ [email protected]:
668681
escape-string-regexp "^1.0.5"
669682
supports-color "^5.3.0"
670683

684+
chalk@^3.0.0:
685+
version "3.0.0"
686+
resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
687+
integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==
688+
dependencies:
689+
ansi-styles "^4.1.0"
690+
supports-color "^7.1.0"
691+
671692
chokidar@^2.0.2, chokidar@^2.1.8:
672693
version "2.1.8"
673694
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917"
@@ -755,11 +776,23 @@ color-convert@^1.9.0:
755776
dependencies:
756777
color-name "1.1.3"
757778

779+
color-convert@^2.0.1:
780+
version "2.0.1"
781+
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
782+
integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
783+
dependencies:
784+
color-name "~1.1.4"
785+
758786
759787
version "1.1.3"
760788
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
761789
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
762790

791+
color-name@~1.1.4:
792+
version "1.1.4"
793+
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
794+
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
795+
763796
commander@^2.20.0:
764797
version "2.20.3"
765798
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
@@ -1617,6 +1650,11 @@ has-flag@^3.0.0:
16171650
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
16181651
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
16191652

1653+
has-flag@^4.0.0:
1654+
version "4.0.0"
1655+
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
1656+
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
1657+
16201658
has-unicode@^2.0.0:
16211659
version "2.0.1"
16221660
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
@@ -3560,6 +3598,13 @@ supports-color@^5.3.0:
35603598
dependencies:
35613599
has-flag "^3.0.0"
35623600

3601+
supports-color@^7.1.0:
3602+
version "7.1.0"
3603+
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1"
3604+
integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==
3605+
dependencies:
3606+
has-flag "^4.0.0"
3607+
35633608
tapable@^1.0.0, tapable@^1.1.3:
35643609
version "1.1.3"
35653610
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"

0 commit comments

Comments
 (0)