Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reorganize files and functions #263

Merged
merged 1 commit into from Nov 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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.