Skip to content

Commit

Permalink
Merge pull request #263 from bmish/refactor-1
Browse files Browse the repository at this point in the history
  • Loading branch information
bmish committed Nov 21, 2022
2 parents 251d373 + 4d86aa2 commit c699064
Show file tree
Hide file tree
Showing 32 changed files with 118 additions and 107 deletions.
30 changes: 9 additions & 21 deletions lib/cli.ts
@@ -1,28 +1,16 @@
import { Command, Argument, Option } from 'commander';
import { readFileSync } from 'node:fs';
import { RULE_DOC_TITLE_FORMATS } from './rule-doc-title-format.js';
import { OPTION_DEFAULTS, OPTION_TYPE, GenerateOptions } from './options.js';
import { OPTION_DEFAULTS } from './options.js';
import { cosmiconfig } from 'cosmiconfig';
import Ajv from 'ajv';
import merge from 'deepmerge';
import { COLUMN_TYPE, NOTICE_TYPE } from './types.js';
import type { PackageJson } from 'type-fest';

function getCurrentPackageVersion(): string {
// When running as compiled code, use path relative to compiled version of this file in the dist folder.
// When running as TypeScript (in a test), use path relative to this file.
const pathToPackageJson = import.meta.url.endsWith('.ts')
? '../package.json'
: /* istanbul ignore next -- can't test the compiled version in test */
'../../package.json';
const packageJson: PackageJson = JSON.parse(
readFileSync(new URL(pathToPackageJson, import.meta.url), 'utf8')
);
if (!packageJson.version) {
throw new Error('Could not find package.json `version`.');
}
return packageJson.version;
}
import {
COLUMN_TYPE,
NOTICE_TYPE,
GenerateOptions,
OPTION_TYPE,
} from './types.js';
import { getCurrentPackageVersion } from './package-json.js';

/** Used for collecting repeated CLI options into an array. */
function collect(value: string, previous: string[]) {
Expand All @@ -37,7 +25,7 @@ function parseBoolean(value: string | undefined): boolean {
* Load and validate the config file.
* Cosmiconfig supports many possible filenames/formats.
*/
async function loadConfigFileOptions() {
async function loadConfigFileOptions(): Promise<GenerateOptions> {
const explorer = cosmiconfig('eslint-doc-generator');
const explorerResults = await explorer.search();
if (explorerResults && !explorerResults.isEmpty) {
Expand Down
File renamed without changes.
11 changes: 6 additions & 5 deletions lib/generator.ts
Expand Up @@ -8,18 +8,19 @@ import {
getPathWithExactFileNameCasing,
} from './package-json.js';
import { updateRulesList } from './rule-list.js';
import { generateRuleHeaderLines } from './rule-notices.js';
import { generateRuleHeaderLines } from './rule-doc-notices.js';
import {
parseRuleDocNoticesOption,
parseRuleListColumnsOption,
parseConfigEmojiOptions,
} from './option-parsers.js';
import { END_RULE_HEADER_MARKER } from './markers.js';
import { END_RULE_HEADER_MARKER } from './comment-markers.js';
import { findSectionHeader, replaceOrCreateHeader } from './markdown.js';
import { resolveConfigsToRules } from './config-resolution.js';
import { OPTION_DEFAULTS, OPTION_TYPE, GenerateOptions } from './options.js';
import { resolveConfigsToRules } from './plugin-config-resolution.js';
import { OPTION_DEFAULTS } from './options.js';
import { diff } from 'jest-diff';
import type { RuleDetails } from './types.js';
import type { RuleDetails, GenerateOptions } from './types.js';
import { OPTION_TYPE } from './types.js';

/**
* Ensure a rule doc contains (or doesn't contain) some particular content.
Expand Down
39 changes: 1 addition & 38 deletions lib/options.ts
@@ -1,5 +1,5 @@
import { RuleDocTitleFormat } from './rule-doc-title-format.js';
import { COLUMN_TYPE, NOTICE_TYPE } from './types.js';
import { COLUMN_TYPE, NOTICE_TYPE,OPTION_TYPE } from './types.js';

export const COLUMN_TYPE_DEFAULT_PRESENCE_AND_ORDERING: {
[key in COLUMN_TYPE]: boolean;
Expand Down Expand Up @@ -35,25 +35,6 @@ export const NOTICE_TYPE_DEFAULT_PRESENCE_AND_ORDERING: {
[NOTICE_TYPE.TYPE]: false,
};

export enum OPTION_TYPE {
CHECK = 'check',
CONFIG_EMOJI = 'configEmoji',
IGNORE_CONFIG = 'ignoreConfig',
IGNORE_DEPRECATED_RULES = 'ignoreDeprecatedRules',
INIT_RULE_DOCS = 'initRuleDocs',
PATH_RULE_DOC = 'pathRuleDoc',
PATH_RULE_LIST = 'pathRuleList',
RULE_DOC_NOTICES = 'ruleDocNotices',
RULE_DOC_SECTION_EXCLUDE = 'ruleDocSectionExclude',
RULE_DOC_SECTION_INCLUDE = 'ruleDocSectionInclude',
RULE_DOC_SECTION_OPTIONS = 'ruleDocSectionOptions',
RULE_DOC_TITLE_FORMAT = 'ruleDocTitleFormat',
RULE_LIST_COLUMNS = 'ruleListColumns',
SPLIT_BY = 'splitBy',
URL_CONFIGS = 'urlConfigs',
URL_RULE_DOC = 'urlRuleDoc',
}

const DEFAULT_RULE_DOC_TITLE_FORMAT: RuleDocTitleFormat =
'desc-parens-prefix-name'; // Using this variable ensures this default has the correct type (not just a plain string).

Expand Down Expand Up @@ -87,21 +68,3 @@ export const OPTION_DEFAULTS = {
// eslint-disable-next-line prettier/prettier -- TODO: waiting on prettier support for TypeScript 4.9: https://github.com/prettier/prettier/issues/13516.
} satisfies Record<OPTION_TYPE, unknown>; // Satisfies is used to ensure all options are included, but without losing type information.

export type GenerateOptions = {
check?: boolean;
configEmoji?: string[];
ignoreConfig?: string[];
ignoreDeprecatedRules?: boolean;
initRuleDocs?: boolean;
pathRuleDoc?: string;
pathRuleList?: string;
ruleDocNotices?: string;
ruleDocSectionExclude?: string[];
ruleDocSectionInclude?: string[];
ruleDocSectionOptions?: boolean;
ruleDocTitleFormat?: RuleDocTitleFormat;
ruleListColumns?: string;
splitBy?: string;
urlConfigs?: string;
urlRuleDoc?: string;
};
16 changes: 16 additions & 0 deletions lib/package-json.ts
Expand Up @@ -105,3 +105,19 @@ export function getPathWithExactFileNameCasing(path: string) {
}
return undefined; // eslint-disable-line unicorn/no-useless-undefined
}

export function getCurrentPackageVersion(): string {
// When running as compiled code, use path relative to compiled version of this file in the dist folder.
// When running as TypeScript (in a test), use path relative to this file.
const pathToPackageJson = import.meta.url.endsWith('.ts')
? '../package.json'
: /* istanbul ignore next -- can't test the compiled version in test */
'../../package.json';
const packageJson: PackageJson = JSON.parse(
readFileSync(new URL(pathToPackageJson, import.meta.url), 'utf8')
);
if (!packageJson.version) {
throw new Error('Could not find package.json `version`.');
}
return packageJson.version;
}
File renamed without changes.
33 changes: 33 additions & 0 deletions lib/configs.ts → lib/plugin-configs.ts
Expand Up @@ -103,3 +103,36 @@ export function findConfigEmoji(

return emoji;
}

/**
* Get the emojis for the configs that set a rule to a certain severity.
*/
export function getEmojisForConfigsSettingRuleToSeverity(
ruleName: string,
configsToRulesWithoutIgnored: ConfigsToRules,
pluginPrefix: string,
configEmojis: ConfigEmojis,
severityType: SEVERITY_TYPE
) {
const configsOfThisSeverity = getConfigsForRule(
ruleName,
configsToRulesWithoutIgnored,
pluginPrefix,
severityType
);

const emojis: string[] = [];
for (const configName of configsOfThisSeverity) {
// Find the emoji for each config or otherwise use a badge that can be defined in markdown.
const emoji = findConfigEmoji(configEmojis, configName, {
fallback: 'badge',
});
/* istanbul ignore next -- this shouldn't happen */
if (typeof emoji !== 'string') {
throw new TypeError('Emoji will always be a string thanks to fallback');
}
emojis.push(emoji);
}

return emojis;
}
8 changes: 4 additions & 4 deletions lib/rule-notices.ts → lib/rule-doc-notices.ts
@@ -1,4 +1,4 @@
import { END_RULE_HEADER_MARKER } from './markers.js';
import { END_RULE_HEADER_MARKER } from './comment-markers.js';
import {
EMOJI_DEPRECATED,
EMOJI_FIXABLE,
Expand All @@ -7,7 +7,7 @@ import {
EMOJI_CONFIG_FROM_SEVERITY,
EMOJI_OPTIONS,
} from './emojis.js';
import { findConfigEmoji, getConfigsForRule } from './configs.js';
import { findConfigEmoji, getConfigsForRule } from './plugin-configs.js';
import {
RuleModule,
Plugin,
Expand Down Expand Up @@ -382,7 +382,7 @@ function removeTrailingPeriod(str: string) {
return str.replace(/\.$/, '');
}

function makeTitle(
function makeRuleDocTitle(
name: string,
description: string | undefined,
pluginPrefix: string,
Expand Down Expand Up @@ -451,7 +451,7 @@ export function generateRuleHeaderLines(
urlRuleDoc?: string
): string {
return [
makeTitle(name, description, pluginPrefix, ruleDocTitleFormat),
makeRuleDocTitle(name, description, pluginPrefix, ruleDocTitleFormat),
...getRuleNoticeLines(
name,
plugin,
Expand Down
2 changes: 1 addition & 1 deletion lib/rule-list-columns.ts
Expand Up @@ -9,7 +9,7 @@ import {
} from './emojis.js';
import { RULE_TYPES } from './rule-type.js';
import { COLUMN_TYPE, SEVERITY_TYPE } from './types.js';
import { getConfigsThatSetARule } from './configs.js';
import { getConfigsThatSetARule } from './plugin-configs.js';
import { hasOptions } from './rule-options.js';
import type { RuleDetails, ConfigsToRules, Plugin } from './types.js';

Expand Down
2 changes: 1 addition & 1 deletion lib/legend.ts → lib/rule-list-legend.ts
Expand Up @@ -7,7 +7,7 @@ import {
EMOJI_TYPE,
EMOJI_CONFIG_FROM_SEVERITY,
} from './emojis.js';
import { findConfigEmoji, getConfigsThatSetARule } from './configs.js';
import { findConfigEmoji, getConfigsThatSetARule } from './plugin-configs.js';
import {
COLUMN_TYPE,
ConfigEmojis,
Expand Down
42 changes: 6 additions & 36 deletions lib/rule-list.ts
@@ -1,16 +1,19 @@
import { BEGIN_RULE_LIST_MARKER, END_RULE_LIST_MARKER } from './markers.js';
import {
BEGIN_RULE_LIST_MARKER,
END_RULE_LIST_MARKER,
} from './comment-markers.js';
import {
EMOJI_DEPRECATED,
EMOJI_FIXABLE,
EMOJI_HAS_SUGGESTIONS,
EMOJI_OPTIONS,
EMOJI_REQUIRES_TYPE_CHECKING,
} from './emojis.js';
import { getConfigsForRule, findConfigEmoji } from './configs.js';
import { getEmojisForConfigsSettingRuleToSeverity } from './plugin-configs.js';
import { getColumns, COLUMN_HEADER } from './rule-list-columns.js';
import { findSectionHeader } from './markdown.js';
import { getPluginRoot } from './package-json.js';
import { generateLegend } from './legend.js';
import { generateLegend } from './rule-list-legend.js';
import { relative } from 'node:path';
import { COLUMN_TYPE, SEVERITY_TYPE } from './types.js';
import { markdownTable } from 'markdown-table';
Expand Down Expand Up @@ -61,39 +64,6 @@ function getPropertyFromRule(
return result;
}

/**
* Get the emojis for the configs that set a rule to a certain severity.
*/
function getEmojisForConfigsSettingRuleToSeverity(
ruleName: string,
configsToRulesWithoutIgnored: ConfigsToRules,
pluginPrefix: string,
configEmojis: ConfigEmojis,
severityType: SEVERITY_TYPE
) {
const configsOfThisSeverity = getConfigsForRule(
ruleName,
configsToRulesWithoutIgnored,
pluginPrefix,
severityType
);

const emojis: string[] = [];
for (const configName of configsOfThisSeverity) {
// Find the emoji for each config or otherwise use a badge that can be defined in markdown.
const emoji = findConfigEmoji(configEmojis, configName, {
fallback: 'badge',
});
/* istanbul ignore next -- this shouldn't happen */
if (typeof emoji !== 'string') {
throw new TypeError('Emoji will always be a string thanks to fallback');
}
emojis.push(emoji);
}

return emojis;
}

function getConfigurationColumnValueForRule(
rule: RuleDetails,
configsToRules: ConfigsToRules,
Expand Down
40 changes: 40 additions & 0 deletions lib/types.ts
@@ -1,3 +1,4 @@
import type { RuleDocTitleFormat } from './rule-doc-title-format.js';
import type { TSESLint, JSONSchema } from '@typescript-eslint/utils';

// Standard ESLint types.
Expand Down Expand Up @@ -81,3 +82,42 @@ export enum COLUMN_TYPE {
REQUIRES_TYPE_CHECKING = 'requiresTypeChecking',
TYPE = 'type',
}

export enum OPTION_TYPE {
CHECK = 'check',
CONFIG_EMOJI = 'configEmoji',
IGNORE_CONFIG = 'ignoreConfig',
IGNORE_DEPRECATED_RULES = 'ignoreDeprecatedRules',
INIT_RULE_DOCS = 'initRuleDocs',
PATH_RULE_DOC = 'pathRuleDoc',
PATH_RULE_LIST = 'pathRuleList',
RULE_DOC_NOTICES = 'ruleDocNotices',
RULE_DOC_SECTION_EXCLUDE = 'ruleDocSectionExclude',
RULE_DOC_SECTION_INCLUDE = 'ruleDocSectionInclude',
RULE_DOC_SECTION_OPTIONS = 'ruleDocSectionOptions',
RULE_DOC_TITLE_FORMAT = 'ruleDocTitleFormat',
RULE_LIST_COLUMNS = 'ruleListColumns',
SPLIT_BY = 'splitBy',
URL_CONFIGS = 'urlConfigs',
URL_RULE_DOC = 'urlRuleDoc',
}

/** The type for the config file and internal generate() function. */
export type GenerateOptions = {
check?: boolean;
configEmoji?: string[];
ignoreConfig?: string[];
ignoreDeprecatedRules?: boolean;
initRuleDocs?: boolean;
pathRuleDoc?: string;
pathRuleList?: string;
ruleDocNotices?: string;
ruleDocSectionExclude?: string[];
ruleDocSectionInclude?: string[];
ruleDocSectionOptions?: boolean;
ruleDocTitleFormat?: RuleDocTitleFormat;
ruleListColumns?: string;
splitBy?: string;
urlConfigs?: string;
urlRuleDoc?: string;
};
2 changes: 1 addition & 1 deletion test/lib/cli-test.ts
@@ -1,7 +1,7 @@
import * as sinon from 'sinon';
import { run } from '../../lib/cli.js';
import mockFs from 'mock-fs';
import { OPTION_TYPE } from '../../lib/options.js';
import { OPTION_TYPE } from '../../lib/types.js';

const configFileOptionsAll: { [key in OPTION_TYPE]: unknown } = {
check: true,
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit c699064

Please sign in to comment.