Skip to content

Commit a74816e

Browse files
committed
fix(tslint): correctly pad the script contentthis avoids manipulating the tslint ruleset, which is only necessarybecause the padding of vueCompiler does not work for lang="ts" scripts.this also makes vue-cli tslint work with tslint-plugin-prettierprereq for: https://github.com/vuejs/vue-cli/issues/761unexpected upstream behavior:https://github.com/vuejs/vue/blob/dev/src/sfc/parser.js#L119
1 parent 873ad84 commit a74816e

File tree

1 file changed

+47
-29
lines changed
  • packages/@vue/cli-plugin-typescript/lib

1 file changed

+47
-29
lines changed

packages/@vue/cli-plugin-typescript/lib/tslint.js

Lines changed: 47 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -26,38 +26,66 @@ module.exports = function lint (args = {}, api, silent) {
2626

2727
const patchWriteFile = () => {
2828
fs.writeFileSync = (file, content, options) => {
29-
if (isVueFile(file)) {
30-
const parts = vueFileCache.get(path.normalize(file))
31-
if (parts) {
32-
parts.content = content
33-
const { before, after } = parts
34-
content = `${before}\n${content.trim()}\n${after}`
35-
}
29+
const parts = vueFileCache.get(path.normalize(file))
30+
if (!parts) {
31+
return writeFileSync(file, content, options)
3632
}
37-
return writeFileSync(file, content, options)
33+
34+
// update cached content
35+
parts.content = content
36+
37+
content = content.slice(parts.paddingOffset)
38+
// remove one leading and trailing linebreak, if any
39+
content = content.replace(/^\r?\n/, '').replace(/\r?\n$/, '')
40+
41+
const { before, after } = parts
42+
43+
return writeFileSync(file, `${before}\n${content}\n${after}`, options)
3844
}
3945
}
4046

4147
const restoreWriteFile = () => {
4248
fs.writeFileSync = writeFileSync
4349
}
4450

51+
const padContent = (parts) => {
52+
const lineCount = parts.before.split(/\r?\n/g).length
53+
const padding = Array(lineCount).join('//\n')
54+
55+
parts.content = padding + parts.content
56+
parts.paddingOffset = padding.length
57+
}
58+
4559
const parseTSFromVueFile = file => {
60+
file = path.normalize(file)
4661
// If the file has already been cached, don't read the file again. Use the cache instead.
4762
if (vueFileCache.has(file)) {
4863
return vueFileCache.get(file)
4964
}
5065

51-
const content = fs.readFileSync(file, 'utf-8')
52-
const { script } = vueCompiler.parseComponent(content, { pad: 'line' })
53-
if (script && /^tsx?$/.test(script.lang)) {
54-
vueFileCache.set(file, {
55-
before: content.slice(0, script.start),
56-
after: content.slice(script.end),
57-
content: script.content
58-
})
59-
return script
66+
const fileContent = fs.readFileSync(file, 'utf-8')
67+
const { start, end, content, lang } = vueCompiler.parseComponent(fileContent).script || {}
68+
if (!/^tsx?$/.test(lang)) {
69+
return { content: '', lang: 'js' }
70+
}
71+
72+
const parts = {
73+
before: fileContent.slice(0, start),
74+
after: fileContent.slice(end),
75+
content,
76+
lang,
77+
paddingOffset: 0
6078
}
79+
vueFileCache.set(file, parts)
80+
81+
// FIXME pad script content
82+
// this should be done by vueCompiler.parseComponent with options { pad: 'line' },
83+
// but it does this only if no lang is set, so it does not work for lang="ts".
84+
// https://github.com/vuejs/vue/blob/dev/src/sfc/parser.js#L119
85+
// we do it here until upstream dep supports this correctly
86+
padContent(parts)
87+
88+
return parts
6189
}
6290

6391
const program = tslint.Linter.createProgram(api.resolve('tsconfig.json'))
@@ -68,7 +96,7 @@ module.exports = function lint (args = {}, api, silent) {
6896
const getSourceFile = program.getSourceFile
6997
program.getSourceFile = function (file, languageVersion, onError) {
7098
if (isVueFile(file)) {
71-
const { content, lang = 'js' } = parseTSFromVueFile(file) || { content: '', lang: 'js' }
99+
const { content, lang } = parseTSFromVueFile(file)
72100
const contentLang = ts.ScriptKind[lang.toUpperCase()]
73101
return ts.createSourceFile(file, content, languageVersion, true, contentLang)
74102
} else {
@@ -93,25 +121,15 @@ module.exports = function lint (args = {}, api, silent) {
93121
.find(file => fs.existsSync(file))
94122

95123
const config = tslint.Configuration.findConfiguration(tslintConfigPath).results
96-
// create a patched config that disables the blank lines rule,
97-
// so that we get correct line numbers in error reports for *.vue files.
98-
const vueConfig = Object.assign(config)
99-
const rules = vueConfig.rules = new Map(vueConfig.rules)
100-
const rule = rules.get('no-consecutive-blank-lines')
101-
rules.set('no-consecutive-blank-lines', Object.assign({}, rule, {
102-
ruleSeverity: 'off'
103-
}))
104124

105125
const lint = file => {
106126
const filePath = api.resolve(file)
107-
const isVue = isVueFile(file)
108127
patchWriteFile()
109128
linter.lint(
110129
// append .ts so that tslint apply TS rules
111130
filePath,
112131
'',
113-
// use Vue config to ignore blank lines
114-
isVue ? vueConfig : config
132+
config
115133
)
116134
restoreWriteFile()
117135
}

0 commit comments

Comments
 (0)