From 71980601f8ceb4df00f3e233690b31e29cd1e29e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Vassbotn=20R=C3=B8yne-Helgesen?= Date: Mon, 14 Oct 2024 13:39:51 +0200 Subject: [PATCH] chore!: Upgrade to , and update eslint setup --- .all-contributorsrc | 159 +++++++------------------- .eslintignore | 5 - .eslintrc | 0 .eslintrc.js | 30 ----- README.md | 3 +- eslint.config.mjs | 267 ++++++++++++++++++++++++++++++++++++++++++++ package.json | 28 +++-- src/index.js | 85 +++++++++----- src/utils.js | 34 +++--- 9 files changed, 399 insertions(+), 212 deletions(-) delete mode 100644 .eslintignore create mode 100644 .eslintrc delete mode 100644 .eslintrc.js create mode 100644 eslint.config.mjs diff --git a/.all-contributorsrc b/.all-contributorsrc index bc459f1e..dc71315b 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1,9 +1,7 @@ { "projectName": "prettier-eslint", "projectOwner": "prettier", - "files": [ - "README.md" - ], + "files": ["README.md"], "imageSize": 100, "commit": false, "contributors": [ @@ -12,196 +10,140 @@ "name": "Kent C. Dodds", "avatar_url": "https://avatars.githubusercontent.com/u/1500684?v=3", "profile": "https://kentcdodds.com", - "contributions": [ - "code", - "doc", - "infra", - "test" - ] + "contributions": ["code", "doc", "infra", "test"] }, { "login": "gyandeeps", "name": "Gyandeep Singh", "avatar_url": "https://avatars.githubusercontent.com/u/5554486?v=3", "profile": "http://gyandeeps.com", - "contributions": [ - "review" - ] + "contributions": ["review"] }, { "login": "exdeniz", "name": "Igor Pnev", "avatar_url": "https://avatars.githubusercontent.com/u/682584?v=3", "profile": "https://github.com/exdeniz", - "contributions": [ - "bug" - ] + "contributions": ["bug"] }, { "login": "demoneaux", "name": "Benjamin Tan", "avatar_url": "https://avatars.githubusercontent.com/u/813865?v=3", "profile": "https://demoneaux.github.io/", - "contributions": [ - "question", - "review" - ] + "contributions": ["question", "review"] }, { "login": "edm00se", "name": "Eric McCormick", "avatar_url": "https://avatars.githubusercontent.com/u/622118?v=3", "profile": "https://ericmccormick.io", - "contributions": [ - "code", - "doc", - "test" - ] + "contributions": ["code", "doc", "test"] }, { "login": "lydell", "name": "Simon Lydell", "avatar_url": "https://avatars.githubusercontent.com/u/2142817?v=3", "profile": "https://github.com/lydell", - "contributions": [ - "doc" - ] + "contributions": ["doc"] }, { "login": "tommck", "name": "Tom McKearney", "avatar_url": "https://avatars0.githubusercontent.com/u/981957?v=3", "profile": "https://github.com/tommck", - "contributions": [ - "doc", - "example" - ] + "contributions": ["doc", "example"] }, { "login": "PAkerstrand", "name": "Patrik Åkerstrand", "avatar_url": "https://avatars.githubusercontent.com/u/463105?v=3", "profile": "https://github.com/PAkerstrand", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "loklaan", "name": "Lochlan Bunn", "avatar_url": "https://avatars.githubusercontent.com/u/1560301?v=3", "profile": "https://twitter.com/loklaan", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "danielterwiel", "name": "Daniël Terwiel", "avatar_url": "https://avatars.githubusercontent.com/u/25886902?v=3", "profile": "https://github.com/danielterwiel", - "contributions": [ - "plugin", - "tool" - ] + "contributions": ["plugin", "tool"] }, { "login": "RobinMalfait", "name": "Robin Malfait", "avatar_url": "https://avatars1.githubusercontent.com/u/1834413?v=3", "profile": "https://robinmalfait.com", - "contributions": [ - "tool" - ] + "contributions": ["tool"] }, { "login": "mgmcdermott", "name": "Michael McDermott", "avatar_url": "https://avatars0.githubusercontent.com/u/8161781?v=3", "profile": "http://mgmcdermott.com", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "sheerun", "name": "Adam Stankiewicz", "avatar_url": "https://avatars3.githubusercontent.com/u/292365?v=3", "profile": "http://sheerun.net", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "spudly", "name": "Stephen John Sorensen", "avatar_url": "https://avatars3.githubusercontent.com/u/487068?v=3", "profile": "http://www.stephenjohnsorensen.com/", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "briandipalma", "name": "Brian Di Palma", "avatar_url": "https://avatars2.githubusercontent.com/u/1597820?v=3", "profile": "https://github.com/briandipalma", - "contributions": [ - "bug", - "code" - ] + "contributions": ["bug", "code"] }, { "login": "robwise", "name": "Rob Wise", "avatar_url": "https://avatars0.githubusercontent.com/u/6173488?v=3", "profile": "https://robwise.github.io", - "contributions": [ - "doc", - "code" - ] + "contributions": ["doc", "code"] }, { "login": "Belir", "name": "Patryk Peas", "avatar_url": "https://avatars0.githubusercontent.com/u/4818642?v=3", "profile": "https://github.com/Belir", - "contributions": [ - "bug", - "code", - "test" - ] + "contributions": ["bug", "code", "test"] }, { "login": "0x80", "name": "Thijs Koerselman", "avatar_url": "https://avatars2.githubusercontent.com/u/1193520?v=3", "profile": "http://vauxlab.com", - "contributions": [ - "bug", - "code", - "test" - ] + "contributions": ["bug", "code", "test"] }, { "login": "enriquecaballero", "name": "Enrique Caballero", "avatar_url": "https://avatars3.githubusercontent.com/u/7918284?v=3", "profile": "https://github.com/enriquecaballero", - "contributions": [ - "bug", - "code" - ] + "contributions": ["bug", "code"] }, { "login": "lukaszmoroz", "name": "Łukasz Moroz", "avatar_url": "https://avatars2.githubusercontent.com/u/1408542?v=3", "profile": "https://github.com/lukaszmoroz", - "contributions": [ - "bug", - "test" - ] + "contributions": ["bug", "test"] }, { "login": "zimme", @@ -229,97 +171,70 @@ "name": "Oliver Joseph Ash", "avatar_url": "https://avatars1.githubusercontent.com/u/921609?v=3", "profile": "https://oliverjash.me/", - "contributions": [ - "bug", - "code" - ] + "contributions": ["bug", "code"] }, { "login": "markpalfreeman", "name": "Mark Palfreeman", "avatar_url": "https://avatars1.githubusercontent.com/u/3812133?v=3", "profile": "http://palf.co", - "contributions": [ - "doc" - ] + "contributions": ["doc"] }, { "login": "alexmckenley", "name": "Alex Taylor", "avatar_url": "https://avatars1.githubusercontent.com/u/3639670?v=4", "profile": "https://github.com/alexmckenley", - "contributions": [ - "code", - "test" - ] + "contributions": ["code", "test"] }, { "login": "chinesedfan", "name": "Xianming Zhong", "avatar_url": "https://avatars3.githubusercontent.com/u/1736154?v=4", "profile": "https://github.com/chinesedfan", - "contributions": [ - "test" - ] + "contributions": ["test"] }, { "login": "lewisl9029", "name": "Lewis Liu", "avatar_url": "https://avatars0.githubusercontent.com/u/6934200?v=4", "profile": "https://github.com/lewisl9029", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "hamzahamidi", "name": "Hamza Hamidi", "avatar_url": "https://avatars0.githubusercontent.com/u/22576950?v=4", "profile": "https://hamidihamza.com", - "contributions": [ - "code", - "ideas", - "maintenance", - "tool", - "review" - ] + "contributions": ["code", "ideas", "maintenance", "tool", "review"] }, { "login": "iamrajiv", "name": "Rajiv Ranjan Singh", "avatar_url": "https://avatars0.githubusercontent.com/u/42106787?v=4", "profile": "https://github.com/iamrajiv", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "cy6erskunk", "name": "Igor", "avatar_url": "https://avatars3.githubusercontent.com/u/754849?v=4", "profile": "https://github.com/cy6erskunk", - "contributions": [ - "maintenance" - ] + "contributions": ["maintenance"] }, { "login": "idahogurl", "name": "Rebecca Vest", "avatar_url": "https://avatars.githubusercontent.com/u/10620169?v=4", "profile": "https://campcode.dev/", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "chrisbobbe", "name": "Chris Bobbe", "avatar_url": "https://avatars.githubusercontent.com/u/22248748?v=4", "profile": "https://github.com/chrisbobbe", - "contributions": [ - "bug", - "code" - ] + "contributions": ["bug", "code"] }, { "login": "JounQin", @@ -353,11 +268,17 @@ "name": "Glen Whitney", "avatar_url": "https://avatars.githubusercontent.com/u/3825429?v=4", "profile": "https://github.com/gwhitney", - "contributions": [ - "code" - ] + "contributions": ["code"] + }, + { + "login": "phun-ky", + "name": "Alexander Vassbotn Røyne-Helgesen", + "avatar_url": "https://avatars.githubusercontent.com/u/1714029?v=4", + "profile": "http://phun-ky.net/", + "contributions": ["code", "maintenance"] } ], "repoType": "github", "commitConvention": "none" } + diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 574cfd3d..00000000 --- a/.eslintignore +++ /dev/null @@ -1,5 +0,0 @@ -node_modules -.nyc_output -coverage -dist -tests/fixtures/ diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 00000000..e69de29b diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index f7fac129..00000000 --- a/.eslintrc.js +++ /dev/null @@ -1,30 +0,0 @@ -const config = { - extends: [ - 'kentcdodds', - 'kentcdodds/jest', - 'plugin:node-dependencies/recommended' - ], - parserOptions: { - ecmaVersion: 2021 - }, - rules: { - 'valid-jsdoc': 'off', - 'max-len': 'off', - 'space-before-function-paren': [ - 'error', - { - anonymous: 'never', - named: 'never', - asyncArrow: 'always' - } - ], - 'import/no-import-module-exports': 'off', - 'arrow-parens': ['error', 'as-needed'], - quotes: ['error', 'single', { avoidEscape: true }], - }, - settings: { - 'import/ignore': ['node_modules', 'src'] // Using CommonJS in src - } -}; - -module.exports = config; diff --git a/README.md b/README.md index a735e077..b64b2101 100644 --- a/README.md +++ b/README.md @@ -346,8 +346,9 @@ Thanks goes to these people ([emoji key][emojis]): Rebecca Vest
Rebecca Vest

💻 Chris Bobbe
Chris Bobbe

🐛 💻 JounQin
JounQin

💬 💻 🎨 📖 🤔 🚇 🚧 🔌 📆 👀 ⚠️ 🔧 - Jonathan Rehm
Jonathan Rehm

💻 + Jonathan Rehm
Jonathan Rehm

🐛 💻 Glen Whitney
Glen Whitney

💻 + Alexander Vassbotn Røyne-Helgesen
Alexander Vassbotn Røyne-Helgesen

💻 🚧 diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 00000000..9a228914 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,267 @@ +import { fixupConfigRules, includeIgnoreFile} from '@eslint/compat'; +import { FlatCompat } from '@eslint/eslintrc'; +import js from '@eslint/js'; +import tsParser from '@typescript-eslint/parser'; +import importPlugin from 'eslint-plugin-import'; +import vitest from 'eslint-plugin-vitest'; +import globals from 'globals'; +import prettierConfig from "eslint-config-prettier"; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import compatPlugin from 'eslint-plugin-compat'; +import stylisticEslintPlugin from '@stylistic/eslint-plugin'; +import typescriptEslintPlugin from '@typescript-eslint/eslint-plugin'; +import prettierPlugin from 'eslint-plugin-prettier'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const gitignorePath = path.resolve(__dirname, ".gitignore"); + +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all +}); +export default [ + includeIgnoreFile(gitignorePath),{ + ignores: [ + '**/node_modules', + '**/.nyc_output', + '**/coverage', + '**/dist', + 'src/__mocks__', + 'src/__tests__', + 'tests/fixtures/', + 'babel.config.js', + '.prettierrc.js', + 'package-scripts.js', + 'jest.config.js' + ], + }, + prettierConfig, + ...fixupConfigRules(compat.extends( + 'eslint:recommended', + 'prettier' + )), + { + files: ['src/**/*.js'], + + linterOptions: { + reportUnusedDisableDirectives: true, + }, + plugins: { + import: importPlugin, + '@stylistic': stylisticEslintPlugin, + '@typescript-eslint': typescriptEslintPlugin, + compat: compatPlugin, + prettier: prettierPlugin, + }, + rules: { + '@stylistic/padded-blocks': ['error', 'never'], + '@stylistic/no-multiple-empty-lines': ["error", { max: 1, maxEOF: 0, maxBOF: 0 }], + '@stylistic/comma-dangle': 'error', + quotes: [1, 'single'], + 'no-undef': 2, + 'no-console': ['warn', { + allow: ['warn', 'error'] + }], + 'max-lines': ['error', { + max: 500, + skipBlankLines: false + }], + 'no-unused-vars': 'off', + 'prefer-const': 'error', + 'global-strict': 0, + indent: [1, 2, { + SwitchCase: 1 + }], + '@typescript-eslint/no-explicit-any': 'error', + '@stylistic/no-extra-semi': 1, + 'no-underscore-dangle': 0, + '@stylistic/no-trailing-spaces': [1, { + skipBlankLines: true + }], + '@stylistic/padding-line-between-statements': ['error', { + blankLine: 'always', + prev: '*', + next: 'return' + }, { + blankLine: 'always', + prev: '*', + next: 'export' + }, { + blankLine: 'always', + prev: 'export', + next: 'export' + }, { + blankLine: 'always', + prev: 'export', + next: '*' + }, { + blankLine: 'always', + prev: '*', + next: 'if' + }, { + blankLine: 'always', + prev: 'if', + next: '*' + }, { + blankLine: 'always', + prev: 'const', + next: '*' + }, { + blankLine: 'always', + prev: '*', + next: 'const' + }, { + blankLine: 'always', + prev: 'multiline-const', + next: '*' + }, { + blankLine: 'always', + prev: '*', + next: 'multiline-const' + }, { + blankLine: 'always', + prev: 'let', + next: '*' + }, { + blankLine: 'always', + prev: '*', + next: 'let' + }, { + blankLine: 'always', + prev: 'var', + next: '*' + }, { + blankLine: 'always', + prev: '*', + next: 'var' + }, { + blankLine: 'always', + prev: 'const', + next: 'let' + }, { + blankLine: 'never', + prev: 'const', + next: 'const' + }, { + blankLine: 'always', + prev: 'multiline-const', + next: 'multiline-const' + }, { + blankLine: 'never', + prev: 'let', + next: 'let' + }, { + blankLine: 'never', + prev: 'var', + next: 'var' + }, { + blankLine: 'always', + prev: 'const', + next: 'let' + }, { + blankLine: 'always', + prev: 'const', + next: 'var' + }, { + blankLine: 'always', + prev: 'const', + next: 'multiline-const' + }, { + blankLine: 'always', + prev: 'multiline-const', + next: 'let' + }, { + blankLine: 'always', + prev: 'multiline-const', + next: 'var' + }, { + blankLine: 'always', + prev: 'let', + next: 'var' + }, { + blankLine: 'always', + prev: '*', + next: 'cjs-import' + }, { + blankLine: 'always', + prev: 'cjs-import', + next: '*' + }, { + blankLine: 'never', + prev: 'cjs-import', + next: 'cjs-import' + }], + "@typescript-eslint/no-empty-object-type": "error", + 'no-unreachable': 1, + 'no-alert': 1, + '@stylistic/semi': 1, + 'import/no-unused-modules': [1, { + unusedExports: true, + src: ['./src'] + }], + 'import/no-named-as-default': 0, + 'import/order': ['error', { + groups: ['external', 'builtin', 'internal', 'parent', 'sibling', 'index'], + + pathGroupsExcludedImportTypes: ['internal'], + + alphabetize: { + order: 'asc', + caseInsensitive: true + }, + + 'newlines-between': 'always' + }], + }, + languageOptions: { + globals: { + ...globals.browser, + JSX: true, + process: true, + vi: true, + expect: true, + test: true, + it: true, + describe: true, + afterAll: true, + beforeAll: true, + afterEach: true, + beforeEach: true + }, + parser: tsParser, + ecmaVersion: 'latest', + sourceType: 'module', + + parserOptions: { + ecmaFeatures: { + classes: true, + } + } + }, + settings: { + 'import/resolver': { + typescript: {} + } + }, +}, +{ + files: ['**/__tests__/*.ts', '**/__tests__/*.tsx'], + + plugins: { + vitest + }, + + languageOptions: { + globals: { + ...globals.browser, + ...globals.node + } + }, + + rules: { + 'max-lines': 0 + } +}]; diff --git a/package.json b/package.json index 41edec45..65f0e1f0 100644 --- a/package.json +++ b/package.json @@ -33,10 +33,10 @@ } }, "dependencies": { - "@typescript-eslint/parser": "^6.7.5", "common-tags": "^1.4.0", "dlv": "^1.1.0", - "eslint": "^8.7.0", + "eslint": "^9.12.0", + "globals": "^15.11.0", "indent-string": "^4.0.0", "lodash.merge": "^4.6.0", "loglevel-colored-level-prefix": "^1.0.0", @@ -44,7 +44,7 @@ "pretty-format": "^29.7.0", "require-relative": "^0.8.7", "typescript": "^5.2.2", - "vue-eslint-parser": "^9.1.0" + "vue-eslint-parser": "^9.4.3" }, "devDependencies": { "@babel/cli": "^7.22.9", @@ -52,20 +52,32 @@ "@babel/preset-env": "^7.22.9", "@changesets/changelog-github": "^0.4.8", "@changesets/cli": "^2.26.2", - "@types/eslint": "^8.4.2", + "@eslint/compat": "^1.2.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "^9.12.0", + "@stylistic/eslint-plugin": "^2.9.0", + "@tanstack/eslint-plugin-query": "^5.59.7", + "@typescript-eslint/eslint-plugin": "^8.8.1", + "@typescript-eslint/parser": "^8.8.1", "all-contributors-cli": "^6.7.0", - "eslint-config-kentcdodds": "^20.5.0", - "eslint-plugin-node-dependencies": "^0.11.0", + "eslint-config-prettier": "^9.1.0", + "eslint-import-resolver-typescript": "^3.6.3", + "eslint-plugin-compat": "^6.0.1", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-testing-library": "^6.3.0", + "eslint-plugin-unused-imports": "^4.1.4", + "eslint-plugin-vitest": "^0.5.4", "husky": "^8.0.1", "jest": "^29.6.2", "nps": "^5.7.1", "nps-utils": "^1.3.0", - "prettier-eslint-cli": "^8.0.0", + "prettier-eslint-cli": "^8.0.1", "prettier-plugin-svelte": "^3.1.2", "rimraf": "^5.0.5", "strip-indent": "^3.0.0", "svelte": "^4.2.9", - "svelte-eslint-parser": "^0.33.1" + "svelte-eslint-parser": "^0.41.1" }, "engines": { "node": ">=16.10.0" diff --git a/src/index.js b/src/index.js index 4661b274..961882ff 100644 --- a/src/index.js +++ b/src/index.js @@ -1,20 +1,23 @@ +/* eslint-disable import/no-unused-modules */ /* eslint no-console:0, global-require:0, import/no-dynamic-require:0 */ /* eslint complexity: [1, 13] */ -import fs from 'fs'; -import path from 'path'; -import requireRelative from 'require-relative'; -import prettyFormat from 'pretty-format'; import { oneLine, stripIndent } from 'common-tags'; import indentString from 'indent-string'; -import getLogger from 'loglevel-colored-level-prefix'; import merge from 'lodash.merge'; -import { getESLint, getOptionsForFormatting, requireModule } from './utils'; +import getLogger from 'loglevel-colored-level-prefix'; +import prettier from 'prettier'; +import prettyFormat from 'pretty-format'; +import requireRelative from 'require-relative'; -const logger = getLogger({ prefix: 'prettier-eslint' }); +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; -// CommonJS + ES6 modules... is it worth it? Probably not... -module.exports = format; +import { getESLint, getOptionsForFormatting } from './utils'; + +const __filename = fileURLToPath(import.meta.url); +const logger = getLogger({ prefix: 'prettier-eslint' }); /** * Formats the text with prettier and then eslint based on the given options @@ -24,9 +27,9 @@ module.exports = format; * `text` is not provided. * @param {String} options.text - the text (JavaScript code) to format * @param {String} options.eslintPath - the path to the eslint module to use. - * Will default to require.resolve('eslint') + * Will default to import.meta.resolve('eslint') * @param {String} options.prettierPath - the path to the prettier module. - * Will default to require.resolve('prettier') + * Will default to import.meta.resolve('prettier') * @param {Object} options.eslintConfig - the config to use for formatting * with ESLint. * @param {Object} options.prettierOptions - the options to pass for @@ -42,6 +45,7 @@ module.exports = format; */ async function format(options) { const {output} = await analyze(options); + return output; } @@ -59,6 +63,7 @@ async function format(options) { // eslint-disable-next-line complexity async function analyze(options) { const { logLevel = getDefaultLogLevel() } = options; + logger.setLevel(logLevel); logger.trace('called analyze with options:', prettyFormat(options)); @@ -123,7 +128,6 @@ async function analyze(options) { const onlyPrettier = filePath ? !eslintExtensions.includes(fileExtension) : false; - const prettify = createPrettify(formattingOptions.prettier, prettierPath); if (onlyPrettier) { @@ -131,36 +135,40 @@ async function analyze(options) { } if (['.ts', '.tsx'].includes(fileExtension)) { - formattingOptions.eslint.parser ||= require.resolve( + formattingOptions.eslint.parser ||= import.meta.resolve( '@typescript-eslint/parser' ); } if (['.vue'].includes(fileExtension)) { - formattingOptions.eslint.parser ||= require.resolve('vue-eslint-parser'); + formattingOptions.eslint.parser ||= import.meta.resolve('vue-eslint-parser'); } if (['.svelte'].includes(fileExtension)) { - formattingOptions.eslint.parser ||= require.resolve('svelte-eslint-parser'); + formattingOptions.eslint.parser ||= import.meta.resolve('svelte-eslint-parser'); } const eslintFix = await createEslintFix(formattingOptions.eslint, eslintPath); if (prettierLast) { const eslintFixed = await eslintFix(text, filePath); + return prettify(eslintFixed); } + return eslintFix((await prettify(text)).output, filePath); } function createPrettify(formatOptions, prettierPath) { return async function prettify(param) { - let text = param - let messages = [] + let text = param; + let messages = []; + if (typeof param !== 'string') { - text = param.output - messages = param.text + text = param.output; + messages = param.text; } + logger.debug('calling prettier on text'); logger.trace( stripIndent` @@ -169,10 +177,12 @@ function createPrettify(formatOptions, prettierPath) { ${indentString(text, 2)} ` ); - const prettier = requireModule(prettierPath, 'prettier'); + try { logger.trace('calling prettier.format with the text and prettierOptions'); + const output = await prettier.format(text, formatOptions); + logger.trace('prettier: output === input', output === text); logger.trace( stripIndent` @@ -181,6 +191,7 @@ function createPrettify(formatOptions, prettierPath) { ${indentString(output, 2)} ` ); + return {output, messages}; } catch (error) { logger.error('prettier formatting failed due to a prettier error'); @@ -193,8 +204,10 @@ function createEslintFix(eslintConfig, eslintPath) { return async function eslintFix(text, filePath) { if (Array.isArray(eslintConfig.globals)) { const tempGlobals = {}; + eslintConfig.globals.forEach(g => { const [key, value] = g.split(':'); + tempGlobals[key] = value; }); eslintConfig.globals = tempGlobals; @@ -224,19 +237,24 @@ function createEslintFix(eslintConfig, eslintPath) { delete eslintConfig.settings; const eslint = getESLint(eslintPath, eslintConfig); + try { logger.trace('calling cliEngine.executeOnText with the text'); + const report = await eslint.lintText(text, { filePath, warnIgnored: true }); + logger.trace( 'executeOnText returned the following report:', prettyFormat(report) ); + // default the output to text because if there's nothing // to fix, eslint doesn't provide `output` const [{ output = text, messages }] = await report; + logger.trace('eslint --fix: output === input', output === text); // NOTE: We're ignoring linting errors/warnings here and // defaulting to the given text if there are any @@ -249,6 +267,7 @@ function createEslintFix(eslintConfig, eslintPath) { ${indentString(output, 2)} ` ); + return {output, messages}; } catch (error) { logger.error('eslint fix failed due to an eslint error'); @@ -265,6 +284,7 @@ function getTextFromFilePath(filePath) { the text for file at "${filePath}" ` ); + return fs.readFileSync(filePath, 'utf8'); } catch (error) { logger.error( @@ -282,15 +302,12 @@ function getESLintApiOptions(eslintConfig) { // these options affect what calculateConfigForFile produces return { ignore: eslintConfig.ignore || true, - ignorePath: eslintConfig.ignorePath || null, + ignorePatterns: eslintConfig.ignorePatterns || null, allowInlineConfig: eslintConfig.allowInlineConfig || true, baseConfig: eslintConfig.baseConfig || null, overrideConfig: eslintConfig.overrideConfig || null, overrideConfigFile: eslintConfig.overrideConfigFile || null, - plugins: eslintConfig.plugins || null, - resolvePluginsRelativeTo: eslintConfig.resolvePluginsRelativeTo || null, - rulePaths: eslintConfig.rulePaths || [], - useEslintrc: eslintConfig.useEslintrc || true + plugins: eslintConfig.plugins || null }; } @@ -298,21 +315,26 @@ async function getESLintConfig(filePath, eslintPath, eslintOptions) { if (filePath) { eslintOptions.cwd = path.dirname(filePath); } + logger.trace( oneLine` creating ESLint CLI Engine to get the config for "${filePath || process.cwd()}" ` ); + const eslint = getESLint(eslintPath, getESLintApiOptions(eslintOptions)); try { logger.debug(`getting eslint config for file at "${filePath}"`); + const config = await eslint.calculateConfigForFile(filePath); + logger.trace( `eslint config for "${filePath}" received`, prettyFormat(config) ); + return { ...eslintOptions, ...config @@ -320,12 +342,12 @@ async function getESLintConfig(filePath, eslintPath, eslintOptions) { } catch (error) { // is this noisy? Try setting options.disableLog to false logger.debug('Unable to find config'); + return { rules: {} }; } } function getPrettierConfig(filePath, prettierPath) { - const prettier = requireModule(prettierPath, 'prettier'); return prettier.resolveConfig && prettier.resolveConfig(filePath); } @@ -341,7 +363,8 @@ function getModulePath(filePath = __filename, moduleName) { error.message, error.stack ); - return require.resolve(moduleName); + + return import.meta.resolve(moduleName); } } @@ -351,5 +374,9 @@ function getDefaultLogLevel() { // Allow named imports of either `analyze` or `format` from this module, // while leaving `format` in place as the default import: -module.exports.format = format -module.exports.analyze = analyze +export default format; + +export { + format, + analyze +}; \ No newline at end of file diff --git a/src/utils.js b/src/utils.js index 02e19ea1..6d87375b 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,16 +1,18 @@ -/* eslint import/no-dynamic-require:0 */ import { oneLine } from 'common-tags'; import delve from 'dlv'; -import getLogger from 'loglevel-colored-level-prefix'; import { Linter } from 'eslint'; +import {ESLint} from 'eslint'; +import getLogger from 'loglevel-colored-level-prefix'; const logger = getLogger({ prefix: 'prettier-eslint' }); const RULE_DISABLED = {}; const RULE_NOT_CONFIGURED = 'RULE_NOT_CONFIGURED'; + const ruleValueExists = prettierRuleValue => prettierRuleValue !== RULE_NOT_CONFIGURED && prettierRuleValue !== RULE_DISABLED && typeof prettierRuleValue !== 'undefined'; + const OPTION_GETTERS = { printWidth: { ruleValue: rules => getRuleValue(rules, 'max-len', 'code'), @@ -19,9 +21,11 @@ const OPTION_GETTERS = { tabWidth: { ruleValue: rules => { let value = getRuleValue(rules, 'indent'); + if (value === 'tab') { value = getRuleValue(rules, 'max-len', 'tabWidth'); } + return value; }, ruleValueToPrettierOption: getTabWidth @@ -58,7 +62,7 @@ const OPTION_GETTERS = { }; /* eslint import/prefer-default-export:0 */ -export { getESLint, getOptionsForFormatting, requireModule }; +export { getESLint, getOptionsForFormatting }; function getOptionsForFormatting( eslintConfig, @@ -66,17 +70,20 @@ function getOptionsForFormatting( fallbackPrettierOptions = {} ) { const eslint = getRelevantESLintConfig(eslintConfig); + const prettier = getPrettierOptionsFromESLintRules( eslintConfig, prettierOptions, fallbackPrettierOptions ); + return { eslint, prettier }; } function getRelevantESLintConfig(eslintConfig) { const linter = new Linter(); const rules = linter.getRules(); + logger.debug('turning off unfixable rules'); const relevantRules = {}; @@ -114,7 +121,6 @@ function getPrettierOptionsFromESLintRules( fallbackPrettierOptions ) { const { rules } = eslintConfig; - const prettierPluginOptions = getRuleValue(rules, 'prettier/prettier', []); if (ruleValueExists(prettierPluginOptions)) { @@ -350,6 +356,7 @@ function getRuleValue(rules, name, objPath) { non-object value of ${value}. Using that value. ` ); + return value; } } @@ -367,6 +374,7 @@ function makePrettierOption(prettierRuleName, prettierRuleValue, fallbacks) { } const fallback = fallbacks[prettierRuleName]; + if (typeof fallback !== 'undefined') { logger.debug( oneLine` @@ -374,6 +382,7 @@ function makePrettierOption(prettierRuleName, prettierRuleValue, fallbacks) { using provided fallback of ${fallback} ` ); + return fallback; } @@ -383,26 +392,11 @@ function makePrettierOption(prettierRuleName, prettierRuleValue, fallbacks) { let prettier decide ` ); - return undefined; -} -function requireModule(modulePath, name) { - try { - logger.trace(`requiring "${name}" module at "${modulePath}"`); - return require(modulePath); - } catch (error) { - logger.error( - oneLine` - There was trouble getting "${name}". - Is "${modulePath}" a correct path to the "${name}" module? - ` - ); - throw error; - } + return undefined; } function getESLint(eslintPath, eslintOptions) { - const { ESLint } = requireModule(eslintPath, 'eslint'); try { return new ESLint(eslintOptions); } catch (error) {