Skip to content

Commit 5b43438

Browse files
author
Guillaume Chau
committed
Merge branch 'dev' of github.com:vuejs/vue-cli into dev
2 parents 4009878 + 844d69b commit 5b43438

File tree

4 files changed

+118
-51
lines changed

4 files changed

+118
-51
lines changed

packages/@vue/cli-plugin-typescript/__tests__/tsPluginTSLint.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
jest.setTimeout(10000)
1+
jest.setTimeout(30000)
22

33
const create = require('@vue/cli-test-utils/createTestProject')
44

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

Lines changed: 74 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,93 +4,117 @@ module.exports = function lint (args = {}, api, silent) {
44
const path = require('path')
55
const globby = require('globby')
66
const tslint = require('tslint')
7+
const ts = require('typescript')
78
/* eslint-disable-next-line node/no-extraneous-require */
89
const vueCompiler = require('vue-template-compiler')
10+
const isVueFile = file => /\.vue(\.ts)?$/.test(file)
911

1012
const options = {
1113
fix: args['fix'] !== false,
1214
formatter: args.format || 'codeFrame',
1315
formattersDirectory: args['formatters-dir'],
1416
rulesDirectory: args['rules-dir']
1517
}
16-
const linter = new tslint.Linter(options)
1718

18-
const config = tslint.Configuration.findConfiguration(api.resolve('tslint.json')).results
19-
// create a patched config that disables the blank lines rule,
20-
// so that we get correct line numbers in error reports for *.vue files.
21-
const vueConfig = Object.assign(config)
22-
const rules = vueConfig.rules = new Map(vueConfig.rules)
23-
const rule = rules.get('no-consecutive-blank-lines')
24-
rules.set('no-consecutive-blank-lines', Object.assign({}, rule, {
25-
ruleSeverity: 'off'
26-
}))
27-
28-
// hack to make tslint --fix work for *.vue files
29-
// this works because (luckily) tslint lints synchronously
19+
// hack to make tslint --fix work for *.vue files:
20+
// we save the non-script parts to a cache right before
21+
// linting the file, and patch fs.writeFileSync to combine the fixed script
22+
// back with the non-script parts.
23+
// this works because (luckily) tslint lints synchronously.
3024
const vueFileCache = new Map()
3125
const writeFileSync = fs.writeFileSync
26+
3227
const patchWriteFile = () => {
3328
fs.writeFileSync = (file, content, options) => {
34-
if (/\.vue(\.ts)?$/.test(file)) {
35-
file = file.replace(/\.ts$/, '')
29+
if (isVueFile(file)) {
3630
const { before, after } = vueFileCache.get(path.normalize(file))
3731
content = `${before}\n${content.trim()}\n${after}`
3832
}
3933
return writeFileSync(file, content, options)
4034
}
4135
}
36+
4237
const restoreWriteFile = () => {
4338
fs.writeFileSync = writeFileSync
4439
}
4540

46-
const lint = file => new Promise((resolve, reject) => {
47-
const filePath = api.resolve(file)
48-
fs.readFile(filePath, 'utf-8', (err, content) => {
49-
if (err) return reject(err)
50-
const isVue = /\.vue(\.ts)?$/.test(file)
51-
if (isVue) {
52-
const { script } = vueCompiler.parseComponent(content, { pad: 'line' })
53-
if (script) {
54-
vueFileCache.set(filePath, {
55-
before: content.slice(0, script.start),
56-
after: content.slice(script.end)
57-
})
58-
}
59-
content = script && script.content
60-
}
61-
if (content) {
62-
patchWriteFile()
63-
linter.lint(
64-
// append .ts so that tslint apply TS rules
65-
`${filePath}${isVue ? `.ts` : ``}`,
66-
content,
67-
// use Vue config to ignore blank lines
68-
isVue ? vueConfig : config
69-
)
70-
restoreWriteFile()
41+
const parseTSFromVueFile = file => {
42+
const content = fs.readFileSync(file, 'utf-8')
43+
const { script } = vueCompiler.parseComponent(content, { pad: 'line' })
44+
if (script) {
45+
vueFileCache.set(file, {
46+
before: content.slice(0, script.start),
47+
after: content.slice(script.end)
48+
})
49+
}
50+
return script && script.content
51+
}
52+
53+
const program = tslint.Linter.createProgram(api.resolve('tsconfig.json'))
54+
55+
// patch getSourceFile for *.vue files
56+
// so that it returns the <script> block only
57+
const patchProgram = program => {
58+
const getSourceFile = program.getSourceFile
59+
program.getSourceFile = function (file, languageVersion, onError) {
60+
if (isVueFile(file)) {
61+
const script = parseTSFromVueFile(file)
62+
return ts.createSourceFile(file, script, languageVersion, true)
63+
} else {
64+
return getSourceFile.call(this, file, languageVersion, onError)
7165
}
72-
resolve()
73-
})
74-
})
66+
}
67+
}
68+
69+
patchProgram(program)
70+
71+
const linter = new tslint.Linter(options, program)
72+
73+
// patch linter.updateProgram to ensure every program has correct getSourceFile
74+
const updateProgram = linter.updateProgram
75+
linter.updateProgram = function (...args) {
76+
updateProgram.call(this, ...args)
77+
patchProgram(this.program)
78+
}
79+
80+
const config = tslint.Configuration.findConfiguration(api.resolve('tslint.json')).results
81+
// create a patched config that disables the blank lines rule,
82+
// so that we get correct line numbers in error reports for *.vue files.
83+
const vueConfig = Object.assign(config)
84+
const rules = vueConfig.rules = new Map(vueConfig.rules)
85+
const rule = rules.get('no-consecutive-blank-lines')
86+
rules.set('no-consecutive-blank-lines', Object.assign({}, rule, {
87+
ruleSeverity: 'off'
88+
}))
89+
90+
const lint = file => {
91+
const filePath = api.resolve(file)
92+
const isVue = isVueFile(file)
93+
patchWriteFile()
94+
linter.lint(
95+
// append .ts so that tslint apply TS rules
96+
filePath,
97+
'',
98+
// use Vue config to ignore blank lines
99+
isVue ? vueConfig : config
100+
)
101+
restoreWriteFile()
102+
}
75103

76104
const files = args._ && args._.length
77105
? args._
78106
: ['src/**/*.ts', 'src/**/*.vue', 'src/**/*.tsx', 'tests/**/*.ts', 'tests/**/*.tsx']
79107

80-
const stripTsExtension = str => str.replace(/\.vue\.ts\b/g, '.vue')
81-
82108
return globby(files, { cwd }).then(files => {
83-
return Promise.all(files.map(lint))
84-
}).then(() => {
109+
files.forEach(lint)
85110
if (silent) return
86-
87111
const result = linter.getResult()
88112
if (result.output.trim()) {
89-
process.stdout.write(stripTsExtension(result.output))
113+
process.stdout.write(result.output)
90114
} else if (result.fixes.length) {
91115
// some formatters do not report fixes.
92116
const f = new tslint.Formatters.ProseFormatter()
93-
process.stdout.write(stripTsExtension(f.format(result.failures, result.fixes)))
117+
process.stdout.write(f.format(result.failures, result.fixes))
94118
} else if (!result.failures.length) {
95119
console.log(`No lint errors found.\n`)
96120
}

packages/@vue/cli-service/__tests__/buildLib.spec.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,43 @@ test('build as lib (js)', async () => {
8888
return window.testLib.bar
8989
})).toBe(2)
9090
})
91+
92+
test('build as lib with webpackConfiguration depending on target (js)', async () => {
93+
const project = await create('build-lib-js-webpack-target', defaultPreset)
94+
await project.write('src/a-library.js', `
95+
export default {
96+
foo: 'bar'
97+
}
98+
`)
99+
100+
await project.write('src/main.js', `
101+
export * from 'a-library'
102+
`)
103+
104+
await project.write('vue.config.js', `
105+
const path = require('path')
106+
module.exports = {
107+
configureWebpack: config => {
108+
config.resolve.alias['a-library'] = path.resolve(__dirname, 'src', 'a-library.js')
109+
110+
if (config.output.libraryTarget === 'umd') {
111+
return
112+
}
113+
114+
config.externals = ['a-library']
115+
}
116+
}
117+
`)
118+
119+
const { stdout } = await project.run('vue-cli-service build --target lib --name testLib src/main.js')
120+
expect(stdout).toMatch('Build complete.')
121+
122+
expect(project.has('dist/testLib.umd.js')).toBe(true)
123+
expect(project.has('dist/testLib.common.js')).toBe(true)
124+
125+
const umdContent = await project.read('dist/testLib.umd.js')
126+
expect(umdContent).toContain(`foo: 'bar'`)
127+
128+
const commonContent = await project.read('dist/testLib.common.js')
129+
expect(commonContent).not.toContain(`foo: 'bar'`)
130+
})

packages/@vue/cli-service/lib/commands/build/resolveLibConfig.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ module.exports = (api, { entry, name }, options) => {
7575
.alias
7676
.set('~entry', fullEntryPath)
7777

78+
// set output target before user configureWebpack hooks are applied
79+
config.output.libraryTarget(format)
80+
7881
// set entry/output after user configureWebpack hooks are applied
7982
const rawConfig = api.resolveWebpackConfig(config)
8083

0 commit comments

Comments
 (0)