diff --git a/packages/@vue/cli-plugin-eslint/generator.js b/packages/@vue/cli-plugin-eslint/generator.js index f508bc809..5fad279d9 100644 --- a/packages/@vue/cli-plugin-eslint/generator.js +++ b/packages/@vue/cli-plugin-eslint/generator.js @@ -73,7 +73,7 @@ module.exports = (api, { config, lintOn = [] }) => { } } api.render(files => { - files['tests/unit/.eslintrc'] = JSON.stringify(config, null, 2) + files['tests/unit/.eslintrc.js'] = api.genJSConfig(config) }) } else if (api.hasPlugin('unit-jest')) { const config = { @@ -85,7 +85,7 @@ module.exports = (api, { config, lintOn = [] }) => { } } api.render(files => { - files['tests/unit/.eslintrc'] = JSON.stringify(config, null, 2) + files['tests/unit/.eslintrc.js'] = api.genJSConfig(config) }) } diff --git a/packages/@vue/cli-plugin-typescript/generator/index.js b/packages/@vue/cli-plugin-typescript/generator/index.js index 5435e25b0..4af4a1359 100644 --- a/packages/@vue/cli-plugin-typescript/generator/index.js +++ b/packages/@vue/cli-plugin-typescript/generator/index.js @@ -112,7 +112,7 @@ module.exports = (api, { // delete all js files that have a ts file of the same name // and simply rename other js files to ts const jsRE = /\.js$/ - const excludeRE = /^tests\/e2e\/|\.config\.js$/ + const excludeRE = /^tests\/e2e\/|(\.config|rc)\.js$/ const convertLintFlags = require('../lib/convertLintFlags') api.postProcessFiles(files => { for (const file in files) { diff --git a/packages/@vue/cli-plugin-unit-jest/__tests__/jestGenerator.spec.js b/packages/@vue/cli-plugin-unit-jest/__tests__/jestGenerator.spec.js index 61b79330f..bf460701f 100644 --- a/packages/@vue/cli-plugin-unit-jest/__tests__/jestGenerator.spec.js +++ b/packages/@vue/cli-plugin-unit-jest/__tests__/jestGenerator.spec.js @@ -18,7 +18,7 @@ test('base', async () => { expect(pkg.scripts.test).toBeTruthy() expect(pkg.devDependencies).toHaveProperty('@vue/test-utils') expect(pkg.devDependencies).toHaveProperty('babel-jest') - expect(files['tests/unit/.eslintrc']).toMatch('"jest": true') + expect(files['tests/unit/.eslintrc.js']).toMatch('jest: true') const spec = files['tests/unit/HelloWorld.spec.js'] expect(spec).toMatch(`expect(wrapper.text()).toMatch(msg)`) diff --git a/packages/@vue/cli-plugin-unit-jest/generator/index.js b/packages/@vue/cli-plugin-unit-jest/generator/index.js index 07f20f0da..642b855a6 100644 --- a/packages/@vue/cli-plugin-unit-jest/generator/index.js +++ b/packages/@vue/cli-plugin-unit-jest/generator/index.js @@ -65,12 +65,12 @@ module.exports = api => { if (api.hasPlugin('eslint')) { api.render(files => { - files['tests/unit/.eslintrc'] = JSON.stringify({ + files['tests/unit/.eslintrc.js'] = api.genJSConfig({ env: { jest: true }, rules: { 'import/no-extraneous-dependencies': 'off' } - }, null, 2) + }) }) } } diff --git a/packages/@vue/cli-plugin-unit-mocha/__tests__/mochaGenerator.spec.js b/packages/@vue/cli-plugin-unit-mocha/__tests__/mochaGenerator.spec.js index 316229e03..eadd2069e 100644 --- a/packages/@vue/cli-plugin-unit-mocha/__tests__/mochaGenerator.spec.js +++ b/packages/@vue/cli-plugin-unit-mocha/__tests__/mochaGenerator.spec.js @@ -17,7 +17,7 @@ test('base', async () => { expect(pkg.scripts.test).toBeTruthy() expect(pkg.devDependencies).toHaveProperty('@vue/test-utils') - expect(files['tests/unit/.eslintrc']).toMatch('"mocha": true') + expect(files['tests/unit/.eslintrc.js']).toMatch('mocha: true') const spec = files['tests/unit/HelloWorld.spec.js'] expect(spec).toMatch(`import { expect } from 'chai'`) diff --git a/packages/@vue/cli-plugin-unit-mocha/generator/index.js b/packages/@vue/cli-plugin-unit-mocha/generator/index.js index db1632b4e..40fa7490a 100644 --- a/packages/@vue/cli-plugin-unit-mocha/generator/index.js +++ b/packages/@vue/cli-plugin-unit-mocha/generator/index.js @@ -15,12 +15,12 @@ module.exports = api => { if (api.hasPlugin('eslint')) { api.render(files => { - files['tests/unit/.eslintrc'] = JSON.stringify({ + files['tests/unit/.eslintrc.js'] = api.genJSConfig({ env: { mocha: true }, rules: { 'import/no-extraneous-dependencies': 'off' } - }, null, 2) + }) }) } } diff --git a/packages/@vue/cli/__tests__/Generator.spec.js b/packages/@vue/cli/__tests__/Generator.spec.js index 9a8ef9f4c..57c001271 100644 --- a/packages/@vue/cli/__tests__/Generator.spec.js +++ b/packages/@vue/cli/__tests__/Generator.spec.js @@ -4,6 +4,7 @@ const fs = require('fs') const path = require('path') const Generator = require('../lib/Generator') const { logs } = require('@vue/cli-shared-utils') +const stringifyJS = require('javascript-stringify') // prepare template fixtures const mkdirp = require('mkdirp') @@ -327,7 +328,7 @@ test('api: resolve', () => { test('extract config files', async () => { const configs = { vue: { - lintOnSave: true + lintOnSave: false }, babel: { presets: ['@vue/app'] @@ -357,9 +358,10 @@ test('extract config files', async () => { }) const json = v => JSON.stringify(v, null, 2) - expect(fs.readFileSync('/vue.config.js', 'utf-8')).toMatch('module.exports = {\n lintOnSave: true\n}') + const js = v => `module.exports = ${stringifyJS(v, null, 2)}` + expect(fs.readFileSync('/vue.config.js', 'utf-8')).toMatch(js(configs.vue)) expect(fs.readFileSync('/.babelrc', 'utf-8')).toMatch(json(configs.babel)) - expect(fs.readFileSync('/.postcssrc', 'utf-8')).toMatch(json(configs.postcss)) - expect(fs.readFileSync('/.eslintrc', 'utf-8')).toMatch(json(configs.eslintConfig)) - expect(fs.readFileSync('/jest.config.js', 'utf-8')).toMatch(`module.exports = {\n foo: 'bar'\n}`) + expect(fs.readFileSync('/.postcssrc.js', 'utf-8')).toMatch(js(configs.postcss)) + expect(fs.readFileSync('/.eslintrc.js', 'utf-8')).toMatch(js(configs.eslintConfig)) + expect(fs.readFileSync('/jest.config.js', 'utf-8')).toMatch(js(configs.jest)) }) diff --git a/packages/@vue/cli/__tests__/invoke.spec.js b/packages/@vue/cli/__tests__/invoke.spec.js index 3ebe234af..87fe8932e 100644 --- a/packages/@vue/cli/__tests__/invoke.spec.js +++ b/packages/@vue/cli/__tests__/invoke.spec.js @@ -4,6 +4,8 @@ jest.mock('inquirer') const invoke = require('../lib/invoke') const { expectPrompts } = require('inquirer') const create = require('@vue/cli-test-utils/createTestProject') +const stringifyJS = require('javascript-stringify') +const toJS = v => `module.exports = ${stringifyJS(v, null, 2)}` async function createAndInstall (name) { const project = await create(name, { @@ -26,11 +28,11 @@ async function assertUpdates (project) { 'pre-commit': 'lint-staged' }) - const eslintrc = JSON.parse(await project.read('.eslintrc')) - expect(eslintrc).toEqual({ + const eslintrc = await project.read('.eslintrc.js') + expect(eslintrc).toEqual(toJS({ root: true, extends: ['plugin:vue/essential', '@vue/airbnb'] - }) + })) const lintedMain = await project.read('src/main.js') expect(lintedMain).toMatch(';') // should've been linted in post-generate hook @@ -78,11 +80,11 @@ test('invoke with existing files', async () => { // mock existing vue.config.js await project.write('vue.config.js', `module.exports = { lintOnSave: true }`) - const eslintrc = JSON.parse(await project.read('.eslintrc')) - expect(eslintrc).toEqual({ + const eslintrc = await project.read('.eslintrc.js') + expect(eslintrc).toEqual(toJS({ root: true, extends: ['plugin:vue/essential', 'eslint:recommended'] - }) + })) await project.run(`${require.resolve('../bin/vue')} invoke eslint --config airbnb --lintOn commit`) @@ -104,13 +106,13 @@ test('invoke with existing files (yaml)', async () => { pkg.devDependencies['@vue/cli-plugin-eslint'] = '*' await project.write('package.json', JSON.stringify(pkg, null, 2)) - const eslintrc = JSON.parse(await project.read('.eslintrc')) - expect(eslintrc).toEqual({ + const eslintrc = await project.read('.eslintrc.js') + expect(eslintrc).toEqual(toJS({ root: true, extends: ['plugin:vue/essential', 'eslint:recommended'] - }) + })) - await project.rm(`.eslintrc`) + await project.rm(`.eslintrc.js`) await project.write(`.eslintrc.yml`, ` root: true extends: diff --git a/packages/@vue/cli/lib/GeneratorAPI.js b/packages/@vue/cli/lib/GeneratorAPI.js index f27da24ee..e37bfa598 100644 --- a/packages/@vue/cli/lib/GeneratorAPI.js +++ b/packages/@vue/cli/lib/GeneratorAPI.js @@ -7,6 +7,7 @@ const resolve = require('resolve') const isBinary = require('isbinaryfile') const yaml = require('yaml-front-matter') const mergeDeps = require('./util/mergeDeps') +const stringifyJS = require('javascript-stringify') const { getPluginLink, toShortPluginId } = require('@vue/cli-shared-utils') const isString = val => typeof val === 'string' @@ -191,6 +192,13 @@ class GeneratorAPI { exitLog (msg, type = 'log') { this.generator.exitLogs.push({ id: this.id, msg, type }) } + + /** + * convenience method for generating a js config file from json + */ + genJSConfig (value) { + return `module.exports = ${stringifyJS(value, null, 2)}` + } } function extractCallDir () { diff --git a/packages/@vue/cli/lib/util/configTransforms.js b/packages/@vue/cli/lib/util/configTransforms.js index 5b82e78fe..e0b4ffba2 100644 --- a/packages/@vue/cli/lib/util/configTransforms.js +++ b/packages/@vue/cli/lib/util/configTransforms.js @@ -35,11 +35,20 @@ function makeJSONTransform (filename) { } } -function makeMutliExtensionJSONTransform (filename) { +function makeMutliExtensionJSONTransform (filename, preferJS) { return function transformToMultiExtensions (value, checkExisting, context) { - if (!checkExisting) { - return makeJSONTransform(filename)(value, checkExisting, context) + function defaultTransform () { + if (preferJS) { + return makeJSTransform(`${filename}.js`)(value, false, context) + } else { + return makeJSONTransform(filename)(value, false, context) + } } + + if (!checkExisting) { + return defaultTransform() + } + const absolutePath = path.resolve(context, filename) if (fs.existsSync(absolutePath)) { return makeJSONTransform(filename)(value, checkExisting, context) @@ -52,7 +61,7 @@ function makeMutliExtensionJSONTransform (filename) { } else if (fs.existsSync(`${absolutePath}.yml`)) { return transformYAML(value, `${filename}.yml`, fs.readFileSync(`${absolutePath}.yml`, 'utf-8')) } else { - return makeJSONTransform(filename)(value, false, context) + return defaultTransform() } } } @@ -69,7 +78,7 @@ function transformYAML (value, filename, source) { module.exports = { vue: makeJSTransform('vue.config.js'), babel: makeJSONTransform('.babelrc'), - postcss: makeMutliExtensionJSONTransform('.postcssrc'), - eslintConfig: makeMutliExtensionJSONTransform('.eslintrc'), + postcss: makeMutliExtensionJSONTransform('.postcssrc', true), + eslintConfig: makeMutliExtensionJSONTransform('.eslintrc', true), jest: makeJSTransform('jest.config.js') }