From 2bcb7a7b7311feca3d52ac5b163c8f5c6bd3caad Mon Sep 17 00:00:00 2001 From: Mark Brouch Date: Thu, 19 Dec 2019 17:19:59 -0600 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Create=20generate=20todo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.ts | 33 +++++++++++++++++++++++++++++++++ src/overrides.ts | 33 +++++++++++++++++++++++++++++++++ src/render.ts | 23 +++++++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 src/index.ts create mode 100644 src/overrides.ts create mode 100644 src/render.ts diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..336949f --- /dev/null +++ b/src/index.ts @@ -0,0 +1,33 @@ +import fs from "fs"; +import util from "util"; +import { CLIEngine, Linter } from "eslint"; + +import { renderAsYAML, renderAsJSON } from "./render"; +import { mapReportToOverrides } from "./overrides"; + +const writeFile = util.promisify(fs.writeFile); + +export async function execute( + files: Array, + { + level, + format = "yaml", + path + }: { level: Linter.RuleLevel; format: "yaml" | "json"; path?: string } +): Promise { + const cli = new CLIEngine({}); + + const report = cli.executeOnFiles(files) as CLIEngine.LintReport; + const config = { overrides: mapReportToOverrides(report, level) }; + + const outputPath = + path || `.eslintrc-todo.${format === "yaml" ? "yml" : "json"}`; + + await writeFile( + outputPath, + format === "yaml" ? renderAsYAML(config) : renderAsJSON(config), + { encoding: "utf8" } + ); + + return outputPath; +} diff --git a/src/overrides.ts b/src/overrides.ts new file mode 100644 index 0000000..1f44e75 --- /dev/null +++ b/src/overrides.ts @@ -0,0 +1,33 @@ +import path from "path"; +import { CLIEngine, Linter } from "eslint"; + +function stripEmptyFiles( + results: CLIEngine.LintResult[] +): CLIEngine.LintResult[] { + return results.filter(result => !!result.messages.length); +} + +function stripNullRuleIds(ruleIds: (string | null)[]): string[] { + return ruleIds.filter((ruleId): ruleId is string => ruleId !== null); +} + +export function mapReportToOverrides( + report: CLIEngine.LintReport, + level: Linter.RuleLevel +): Linter.RuleOverride[] { + return stripEmptyFiles(report.results).map((result: CLIEngine.LintResult) => { + const uniqueRuleIds = Array.from( + new Set(result.messages.map(message => message.ruleId)) + ); + + const rules: Linter.RulesRecord = {}; + stripNullRuleIds(uniqueRuleIds).forEach(ruleId => { + rules[ruleId] = level; + }); + + return { + files: [path.relative(process.cwd(), result.filePath)], + rules + }; + }); +} diff --git a/src/render.ts b/src/render.ts new file mode 100644 index 0000000..f42da18 --- /dev/null +++ b/src/render.ts @@ -0,0 +1,23 @@ +import { Linter } from "eslint"; +import yaml from "js-yaml"; + +function generateYAMLCommentBlock(): string { + return `# This configuration was generated by +# \`eslint-generate-todo\` (http://github.com/doximity/eslint-generate-todo) +# +# on ${new Date().toISOString()}. +# +# It contains all the known ESLint errors/warnings, and prevents them from +# showing up as errors until devs can remove them from the code base. +# Regenerate this file as errors are fixed. + +`; +} + +export function renderAsYAML(config: Linter.Config): string { + return `${generateYAMLCommentBlock()}${yaml.dump(config)}`; +} + +export function renderAsJSON(config: Linter.Config): string { + return JSON.stringify(config, null, 2); +}