Skip to content

Commit 5c0d491

Browse files
committed
fix script line numbers for babel/eslint and eslint indentation warning
1 parent a45a497 commit 5c0d491

File tree

3 files changed

+94
-10
lines changed

3 files changed

+94
-10
lines changed

lib/deindent.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// For some reason, if a script code block has a base indent
2+
// level, the eval-source-map gets messed up. So we have to
3+
// manually deindent script code blocks here.
4+
5+
var splitRE = /\r?\n/g
6+
var emptyRE = /^\s*$/
7+
8+
module.exports = function deindent (str) {
9+
var lines = str.split(splitRE)
10+
var min = Infinity
11+
var type, cur, c
12+
for (var i = 0; i < lines.length; i++) {
13+
var line = lines[i]
14+
if (!emptyRE.test(line)) {
15+
if (!type) {
16+
c = line.charAt(0)
17+
if (c === ' ' || c === '\t') {
18+
type = c
19+
} else {
20+
return str
21+
}
22+
} else {
23+
cur = count(line, type)
24+
if (cur < min) {
25+
min = cur
26+
}
27+
}
28+
}
29+
}
30+
return lines.map(function (line) {
31+
return line.slice(min)
32+
}).join('\n')
33+
}
34+
35+
function count (line, type) {
36+
var i = 0
37+
while (line.charAt(i) === type) {
38+
i++
39+
}
40+
return i
41+
}

lib/parser.js

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ var parse5 = require('parse5')
22
var parser = new parse5.Parser(null, { locationInfo: true })
33
var cache = require('lru-cache')(100)
44
var SourceMapGenerator = require('source-map').SourceMapGenerator
5-
var splitRE = /\r?\n/g
6-
var trimRE = /^(\s|\r?\n)+/
75
var hash = require('hash-sum')
6+
var deindent = require('./deindent')
7+
var splitRE = /\r?\n/g
8+
var emptyRE = /^\s*$/
89

910
module.exports = function (content, filename) {
1011

@@ -78,16 +79,28 @@ module.exports = function (content, filename) {
7879
}
7980
}
8081

82+
// extract part
8183
var start = node.childNodes[0].__location.start
8284
var end = node.childNodes[node.childNodes.length - 1].__location.end
83-
var result = content.slice(start, end)
84-
var trimmedResult = result.replace(trimRE, '')
85-
var trimmed = trimmedResult.length - result.length
86-
var lineOffset = content.slice(0, start + trimmed).split(splitRE).length
85+
var result
86+
var lineOffset
87+
if (type === 'script') {
88+
lineOffset = 0
89+
// preserve other parts as commenets so that linters
90+
// and babel can output correct line numbers in warnings
91+
result =
92+
commentScript(content.slice(0, start), lang) +
93+
deindent(content.slice(start, end)) +
94+
commentScript(content.slice(end), lang)
95+
} else {
96+
lineOffset = content.slice(0, start).split(splitRE).length - 1
97+
result = content.slice(start, end)
98+
}
99+
100+
// generate source map
87101
var map = new SourceMapGenerator()
88102
map.setSourceContent(filenameWithHash, content)
89-
90-
trimmedResult.split(splitRE).forEach(function (line, index) {
103+
result.split(splitRE).forEach(function (line, index) {
91104
map.addMapping({
92105
source: filenameWithHash,
93106
original: {
@@ -101,10 +114,18 @@ module.exports = function (content, filename) {
101114
})
102115
})
103116

117+
// workaround for Webpack eval-source-map bug
118+
// https://github.com/webpack/webpack/pull/1816
119+
// in case the script was piped through another loader
120+
// that doesn't pass down the source map properly.
121+
if (type === 'script') {
122+
result += '\n/* generated by vue-loader */\n'
123+
}
124+
104125
output[type].push({
105126
lang: lang,
106127
scoped: scoped,
107-
content: trimmedResult,
128+
content: result,
108129
map: map.toJSON()
109130
})
110131
})
@@ -113,6 +134,28 @@ module.exports = function (content, filename) {
113134
return output
114135
}
115136

137+
function commentScript (content, lang) {
138+
return content
139+
.split(splitRE)
140+
.map(function (line) {
141+
if (emptyRE.test(line)) {
142+
return line
143+
}
144+
switch (lang) {
145+
case 'coffee':
146+
case 'coffee-jsx':
147+
case 'coffee-redux':
148+
return '# ' + line
149+
case 'purs':
150+
case 'ulmus':
151+
return '-- ' + line
152+
default:
153+
return '// ' + line
154+
}
155+
})
156+
.join('\n')
157+
}
158+
116159
function getAttribute (node, name) {
117160
if (node.attrs) {
118161
var i = node.attrs.length

test/test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ describe('vue-loader', function () {
209209
}), function (err) {
210210
expect(err).to.be.null
211211
getFile('test.output.css', function (data) {
212-
expect(data).to.contain('h1 {\n color: #f00;\n}\nh2 {\n color: green;\n}')
212+
expect(data).to.contain('h1 {\n color: #f00;\n}\n\nh2 {\n color: green;\n}')
213213
done()
214214
})
215215
})

0 commit comments

Comments
 (0)