Skip to content

Commit

Permalink
feat: more accurate template source map
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Dec 19, 2019
1 parent d87336b commit 66d2ab8
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 35 deletions.
7 changes: 3 additions & 4 deletions src/pitcher.ts
Expand Up @@ -81,10 +81,9 @@ pitcher.pitch = function() {
return ``
}

// rewrite if we have deduped loaders
if (loaders.length !== rawLoaders.length) {
return genProxyModule(loaders, context)
}
// Rewrite request. Technically this should only be done when we have deduped
// loaders. But somehow this is required for template source map to work...
return genProxyModule(loaders, context)
}

function genProxyModule(
Expand Down
43 changes: 12 additions & 31 deletions src/templateLoader.ts
Expand Up @@ -3,9 +3,7 @@ import qs from 'querystring'
import chalk from 'chalk'
import loaderUtils from 'loader-utils'
import { VueLoaderOptions } from './'
import { SourceMapConsumer, RawSourceMap } from 'source-map'
import { compileTemplate, generateCodeFrame } from '@vue/compiler-sfc'
import mergeSourceMap from 'merge-source-map'

// Loader that compiles raw template into JavaScript functions.
// This is injected by the global pitcher (../pitch) for template
Expand All @@ -27,7 +25,7 @@ const TemplateLoader: webpack.loader.Loader = function(source, inMap) {

const compiled = compileTemplate({
source,
// avoid source content overwriting the original
inMap,
filename: loaderContext.resourcePath,
compiler: options.compiler,
compilerOptions: {
Expand All @@ -46,49 +44,32 @@ const TemplateLoader: webpack.loader.Loader = function(source, inMap) {

// errors
if (compiled.errors && compiled.errors.length) {
const lineOffset = inMap ? getLineOffset(inMap) : 0
compiled.errors.forEach(err => {
if (typeof err === 'string') {
loaderContext.emitError(err)
} else {
if (err.loc) {
const filePath = chalk.gray(
`at ${loaderContext.resourcePath}:${err.loc.start.line +
lineOffset}:${err.loc.start.column}`
const loc = `:${err.loc.start.line}:${err.loc.start.column}`
const filePath = chalk.gray(`at ${loaderContext.resourcePath}${loc}`)
const originalSource = inMap
? inMap.sourcesContent![0]
: (source as string)
const codeframe = generateCodeFrame(
originalSource,
err.loc.start.offset,
err.loc.end.offset
)

err.message = `\n${chalk.red(
`Syntax Error: ${err.message}`
)}\n${filePath}\n${chalk.yellow(
generateCodeFrame(
source as string,
err.loc.start.offset,
err.loc.end.offset,
lineOffset
)
)}\n`
)}\n${filePath}\n${chalk.yellow(codeframe)}\n`
}
loaderContext.emitError(err)
}
})
}

let { code, map } = compiled
if (map && inMap) {
// avoid overwritting original *.vue source during merge
map.sourcesContent = []
map = mergeSourceMap(inMap, map)
}
const { code, map } = compiled
loaderContext.callback(null, code, map)
}

function getLineOffset(map: RawSourceMap): number {
const consumer = new SourceMapConsumer(map)
let offset = 0
consumer.eachMapping(map => {
offset = map.originalLine - map.generatedLine
})
return offset
}

module.exports = TemplateLoader

0 comments on commit 66d2ab8

Please sign in to comment.