diff --git a/.changeset/small-dancers-sin.md b/.changeset/small-dancers-sin.md new file mode 100644 index 0000000..59ce39e --- /dev/null +++ b/.changeset/small-dancers-sin.md @@ -0,0 +1,7 @@ +--- +"@naverpay/eslint-plugin": minor +--- + +auto fix peer-deps-in-dev-deps + +PR: [auto fix peer-deps-in-dev-deps](https://github.com/NaverPayDev/code-style/pull/103) diff --git a/packages/eslint-plugin/lib/rules/peer-deps-in-dev-deps.js b/packages/eslint-plugin/lib/rules/peer-deps-in-dev-deps.js index 877dcae..bcab42c 100644 --- a/packages/eslint-plugin/lib/rules/peer-deps-in-dev-deps.js +++ b/packages/eslint-plugin/lib/rules/peer-deps-in-dev-deps.js @@ -1,4 +1,4 @@ -import path from 'path' +import {getIndentationLength} from '../utils/getIndentationLength.js' /** * @type {import('eslint').Rule.RuleModule} @@ -10,7 +10,7 @@ export default { description: 'Ensure that all peerDependencies are also declared in devDependencies.', recommended: false, }, - fixable: null, + fixable: 'code', schema: [], messages: { missingInDevDeps: "'{{packageName}}' is declared in peerDependencies but not in devDependencies.", @@ -20,7 +20,7 @@ export default { create(context) { return { Program(node) { - const filename = path.basename(context.getFilename()) + const filename = context.filename.replace(context.cwd, '') if (filename !== 'package.json') { return } @@ -46,13 +46,37 @@ export default { (property) => property.key.value === 'devDependencies', ) - for (const [depName] of Object.entries(peerDeps)) { + for (const [depName, depVersion] of Object.entries(peerDeps)) { if (!Object.prototype.hasOwnProperty.call(devDeps, depName)) { context.report({ node, messageId: 'missingInDevDeps', data: {packageName: depName}, loc: devDepsNode?.loc || peerDepsNode?.loc, + fix(fixer) { + const s = ' '.repeat(getIndentationLength(sourceCode.getText())) + const ss = s.repeat(2) + const newDevDep = `"${depName}": "${depVersion}"` + + if (devDepsNode) { + if (devDepsNode.value.properties.length > 0) { + const lastDevDep = + devDepsNode.value.properties[devDepsNode.value.properties.length - 1] + + return fixer.insertTextAfter(lastDevDep, `,\n${ss}${newDevDep}`) + } else { + return fixer.replaceText( + devDepsNode, + `"devDependencies": {\n${ss}${newDevDep}\n${s}}`, + ) + } + } else { + return fixer.insertTextBefore( + peerDepsNode, + `"devDependencies": {\n${ss}${newDevDep}\n${s}},\n${s}`, + ) + } + }, }) } } diff --git a/packages/eslint-plugin/lib/utils/getIndentationLength.js b/packages/eslint-plugin/lib/utils/getIndentationLength.js new file mode 100644 index 0000000..c862a58 --- /dev/null +++ b/packages/eslint-plugin/lib/utils/getIndentationLength.js @@ -0,0 +1,13 @@ +export function getIndentationLength(jsonString) { + const lines = jsonString.split('\n') + + for (const line of lines) { + const trimmedLine = line.trim() + if (trimmedLine.startsWith('"')) { + const leadingWhitespace = line.match(/^\s*/)[0] + return leadingWhitespace.length + } + } + + return 2 +}