Skip to content

Commit

Permalink
Merge pull request #262 from bmish/option-url-rule-doc
Browse files Browse the repository at this point in the history
Add new option `--url-rule-doc`
  • Loading branch information
bmish committed Nov 21, 2022
2 parents c11b203 + 1968ae3 commit d8aa370
Show file tree
Hide file tree
Showing 12 changed files with 175 additions and 32 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ There's also an optional path argument if you need to point the CLI to an ESLint
| `--rule-list-columns` | Ordered, comma-separated list of columns to display in rule list. Empty columns will be hidden. Choices: `configsError`, `configsOff`, `configsWarn`, `deprecated`, `description`, `fixable`, `fixableAndHasSuggestions` (off by default), `hasSuggestions`, `name`, `options` (off by default), `requiresTypeChecking`, `type` (off by default). Default: `name,description,configsError,configsWarn,configsOff,fixable,hasSuggestions,requiresTypeChecking,deprecated`. |
| `--split-by` | Rule property to split the rules list by. A separate list and header will be created for each value. Example: `meta.type`. |
| `--url-configs` | Link to documentation about the ESLint configurations exported by the plugin. |
| `--url-rule-doc` | Link to documentation for each rule. Useful when it differs from the rule doc path on disk (e.g. custom documentation site in use). Use `{name}` placeholder for the rule name. |

### `--rule-doc-title-format`

Expand Down
5 changes: 5 additions & 0 deletions lib/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ async function loadConfigFileOptions() {
ruleListColumns: { type: 'string' },
splitBy: { type: 'string' },
urlConfigs: { type: 'string' },
urlRuleDoc: { type: 'string' },
};
const schema = {
type: 'object',
Expand Down Expand Up @@ -204,6 +205,10 @@ export async function run(
'--url-configs <url>',
'(optional) Link to documentation about the ESLint configurations exported by the plugin.'
)
.option(
'--url-rule-doc <url>',
'(optional) Link to documentation for each rule. Useful when it differs from the rule doc path on disk (e.g. custom documentation site in use). Use `{name}` placeholder for the rule name.'
)
.action(async function (path, options: GenerateOptions) {
// Load config file options and merge with CLI options.
// CLI options take precedence.
Expand Down
6 changes: 5 additions & 1 deletion lib/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ export async function generate(path: string, options?: GenerateOptions) {
const splitBy = options?.splitBy ?? OPTION_DEFAULTS[OPTION_TYPE.SPLIT_BY];
const urlConfigs =
options?.urlConfigs ?? OPTION_DEFAULTS[OPTION_TYPE.URL_CONFIGS];
const urlRuleDoc =
options?.urlRuleDoc ?? OPTION_DEFAULTS[OPTION_TYPE.URL_RULE_DOC];

// Gather details about rules.
const details: RuleDetails[] = Object.entries(plugin.rules)
Expand Down Expand Up @@ -188,7 +190,8 @@ export async function generate(path: string, options?: GenerateOptions) {
ignoreConfig,
ruleDocNotices,
ruleDocTitleFormat,
urlConfigs
urlConfigs,
urlRuleDoc
);

const contents = readFileSync(pathToDoc).toString();
Expand Down Expand Up @@ -260,6 +263,7 @@ export async function generate(path: string, options?: GenerateOptions) {
ignoreConfig,
ruleListColumns,
urlConfigs,
urlRuleDoc,
splitBy
);

Expand Down
3 changes: 3 additions & 0 deletions lib/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export enum OPTION_TYPE {
RULE_LIST_COLUMNS = 'ruleListColumns',
SPLIT_BY = 'splitBy',
URL_CONFIGS = 'urlConfigs',
URL_RULE_DOC = 'urlRuleDoc',
}

const DEFAULT_RULE_DOC_TITLE_FORMAT: RuleDocTitleFormat =
Expand Down Expand Up @@ -82,6 +83,7 @@ export const OPTION_DEFAULTS = {
.join(','),
[OPTION_TYPE.SPLIT_BY]: undefined,
[OPTION_TYPE.URL_CONFIGS]: undefined,
[OPTION_TYPE.URL_RULE_DOC]: undefined,
// 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.

Expand All @@ -101,4 +103,5 @@ export type GenerateOptions = {
ruleListColumns?: string;
splitBy?: string;
urlConfigs?: string;
urlRuleDoc?: string;
};
27 changes: 18 additions & 9 deletions lib/rule-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ function buildRuleRow(
pluginPrefix: string,
pathRuleDoc: string,
configEmojis: ConfigEmojis,
ignoreConfig: string[]
ignoreConfig: string[],
urlRuleDoc?: string
): string[] {
const columns: {
[key in COLUMN_TYPE]: string;
Expand Down Expand Up @@ -164,7 +165,7 @@ function buildRuleRow(
[COLUMN_TYPE.HAS_SUGGESTIONS]: rule.hasSuggestions
? EMOJI_HAS_SUGGESTIONS
: '',
[COLUMN_TYPE.NAME]: `[${rule.name}](${pathRuleDoc.replace(
[COLUMN_TYPE.NAME]: `[${rule.name}](${(urlRuleDoc ?? pathRuleDoc).replace(
/{name}/g,
rule.name
)})`,
Expand All @@ -190,7 +191,8 @@ function generateRulesListMarkdown(
pluginPrefix: string,
pathRuleDoc: string,
configEmojis: ConfigEmojis,
ignoreConfig: string[]
ignoreConfig: string[],
urlRuleDoc?: string
): string {
const listHeaderRow = (
Object.entries(columns) as [COLUMN_TYPE, boolean][]
Expand Down Expand Up @@ -221,7 +223,8 @@ function generateRulesListMarkdown(
pluginPrefix,
pathRuleDoc,
configEmojis,
ignoreConfig
ignoreConfig,
urlRuleDoc
)
),
],
Expand All @@ -241,7 +244,8 @@ function generateRulesListMarkdownWithSplitBy(
pathRuleDoc: string,
configEmojis: ConfigEmojis,
ignoreConfig: string[],
splitBy: string
splitBy: string,
urlRuleDoc?: string
): string {
const values = new Set(
details.map((detail) => getPropertyFromRule(plugin, detail.name, splitBy))
Expand Down Expand Up @@ -278,7 +282,8 @@ function generateRulesListMarkdownWithSplitBy(
pluginPrefix,
pathRuleDoc,
configEmojis,
ignoreConfig
ignoreConfig,
urlRuleDoc
)
);
}
Expand Down Expand Up @@ -309,7 +314,8 @@ function generateRulesListMarkdownWithSplitBy(
pluginPrefix,
pathRuleDoc,
configEmojis,
ignoreConfig
ignoreConfig,
urlRuleDoc
)
);
}
Expand All @@ -330,6 +336,7 @@ export function updateRulesList(
ignoreConfig: string[],
ruleListColumns: COLUMN_TYPE[],
urlConfigs?: string,
urlRuleDoc?: string,
splitBy?: string
): string {
let listStartIndex = markdown.indexOf(BEGIN_RULE_LIST_MARKER);
Expand Down Expand Up @@ -399,7 +406,8 @@ export function updateRulesList(
pathRuleDoc,
configEmojis,
ignoreConfig,
splitBy
splitBy,
urlRuleDoc
)
: generateRulesListMarkdown(
columns,
Expand All @@ -408,7 +416,8 @@ export function updateRulesList(
pluginPrefix,
pathRuleDoc,
configEmojis,
ignoreConfig
ignoreConfig,
urlRuleDoc
);

const newContent = `${legend ? `${legend}\n\n` : ''}${list}`;
Expand Down
30 changes: 22 additions & 8 deletions lib/rule-notices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ const RULE_NOTICES: {
replacedBy: readonly string[] | undefined;
pluginPrefix: string;
type?: RULE_TYPE;
urlRuleDoc?: string;
}) => string);
} = {
// Configs notice varies based on whether the rule is configured in one or more configs.
Expand Down Expand Up @@ -152,7 +153,12 @@ const RULE_NOTICES: {
},

// Deprecated notice has optional "replaced by" rules list.
[NOTICE_TYPE.DEPRECATED]: ({ replacedBy, pluginPrefix, ruleName }) => {
[NOTICE_TYPE.DEPRECATED]: ({
replacedBy,
pluginPrefix,
ruleName,
urlRuleDoc,
}) => {
// Determine the relative path to the rule doc root so that any replacement rule links can account for this.
const slashesInCurrentRuleName = ruleName.match(/\//g);
const nestingDepthOfCurrentRule = slashesInCurrentRuleName?.length ?? 0;
Expand All @@ -163,7 +169,8 @@ const RULE_NOTICES: {
? ` It was replaced by ${ruleNamesToList(
replacedBy,
pluginPrefix,
relativePathToRuleDocRoot
relativePathToRuleDocRoot,
urlRuleDoc
)}.`
: ''
}`;
Expand Down Expand Up @@ -206,7 +213,8 @@ const RULE_NOTICES: {
function ruleNamesToList(
ruleNames: readonly string[],
pluginPrefix: string,
relativePathToRuleDocRoot: string
relativePathToRuleDocRoot: string,
urlRuleDoc?: string
) {
return ruleNames
.map((ruleName) => {
Expand All @@ -218,8 +226,10 @@ function ruleNamesToList(
? ruleName.slice(pluginPrefix.length + 1)
: ruleName;
return `[\`${ruleNameWithoutPluginPrefix}\`](${
relativePathToRuleDocRoot + ruleNameWithoutPluginPrefix
}.md)`;
urlRuleDoc
? urlRuleDoc.replace(/{name}/g, ruleName)
: `${relativePathToRuleDocRoot + ruleNameWithoutPluginPrefix}.md`
})`;
})
.join(', ');
}
Expand Down Expand Up @@ -273,7 +283,8 @@ function getRuleNoticeLines(
configEmojis: ConfigEmojis,
ignoreConfig: string[],
ruleDocNotices: NOTICE_TYPE[],
urlConfigs?: string
urlConfigs?: string,
urlRuleDoc?: string
) {
const lines: string[] = [];

Expand Down Expand Up @@ -352,6 +363,7 @@ function getRuleNoticeLines(
replacedBy: rule.meta?.replacedBy,
pluginPrefix,
type: rule.meta?.type as RULE_TYPE, // Convert union type to enum.
urlRuleDoc,
})
: ruleNoticeStrOrFn
);
Expand Down Expand Up @@ -435,7 +447,8 @@ export function generateRuleHeaderLines(
ignoreConfig: string[],
ruleDocNotices: NOTICE_TYPE[],
ruleDocTitleFormat: RuleDocTitleFormat,
urlConfigs?: string
urlConfigs?: string,
urlRuleDoc?: string
): string {
return [
makeTitle(name, description, pluginPrefix, ruleDocTitleFormat),
Expand All @@ -447,7 +460,8 @@ export function generateRuleHeaderLines(
configEmojis,
ignoreConfig,
ruleDocNotices,
urlConfigs
urlConfigs,
urlRuleDoc
),
'',
END_RULE_HEADER_MARKER,
Expand Down
9 changes: 6 additions & 3 deletions test/lib/__snapshots__/cli-test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ exports[`cli all CLI options and all config files options merges correctly, with
"ruleDocTitleFormat": "name",
"ruleListColumns": "type",
"splitBy": "meta.docs.foo-from-cli",
"urlConfigs": "www.example.com/configs-from-cli",
"urlConfigs": "https://example.com/configs-url-from-cli",
"urlRuleDoc": "https://example.com/rule-doc-url-from-cli",
},
]
`;
Expand Down Expand Up @@ -70,7 +71,8 @@ exports[`cli all CLI options, no config file options is called correctly 1`] = `
"ruleDocTitleFormat": "name",
"ruleListColumns": "type",
"splitBy": "meta.docs.foo-from-cli",
"urlConfigs": "www.example.com/configs-from-cli",
"urlConfigs": "https://example.com/configs-url-from-cli",
"urlRuleDoc": "https://example.com/rule-doc-url-from-cli",
},
]
`;
Expand Down Expand Up @@ -104,7 +106,8 @@ exports[`cli all config files options, no CLI options is called correctly 1`] =
"ruleDocTitleFormat": "desc",
"ruleListColumns": "fixable,hasSuggestions",
"splitBy": "meta.docs.foo-from-config-file",
"urlConfigs": "www.example.com/configs-from-config-file",
"urlConfigs": "https://example.com/configs-url-from-config-file",
"urlRuleDoc": "https://example.com/rule-doc-url-from-config-file",
},
]
`;
Expand Down
10 changes: 8 additions & 2 deletions test/lib/cli-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ const configFileOptionsAll: { [key in OPTION_TYPE]: unknown } = {
ruleDocTitleFormat: 'desc',
ruleListColumns: 'fixable,hasSuggestions',
splitBy: 'meta.docs.foo-from-config-file',
urlConfigs: 'www.example.com/configs-from-config-file',
urlConfigs: 'https://example.com/configs-url-from-config-file',
urlRuleDoc: 'https://example.com/rule-doc-url-from-config-file',
};

const cliOptionsAll: { [key in OPTION_TYPE]: string[] } = {
Expand Down Expand Up @@ -85,7 +86,12 @@ const cliOptionsAll: { [key in OPTION_TYPE]: string[] } = {

[OPTION_TYPE.URL_CONFIGS]: [
'--url-configs',
'www.example.com/configs-from-cli',
'https://example.com/configs-url-from-cli',
],

[OPTION_TYPE.URL_RULE_DOC]: [
'--url-rule-doc',
'https://example.com/rule-doc-url-from-cli',
],
};

Expand Down
14 changes: 7 additions & 7 deletions test/lib/generate/__snapshots__/url-configs-test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ exports[`generate (--url-configs) basic includes the config link 1`] = `
"## Rules
<!-- begin auto-generated rules list -->
💼 [Configurations](http://example.com/configs) enabled in.\\
✅ Set in the \`recommended\` [configuration](http://example.com/configs).
💼 [Configurations](https://example.com/configs) enabled in.\\
✅ Set in the \`recommended\` [configuration](https://example.com/configs).
| Name | Description | 💼 |
| :----------------------------- | :---------------------- | :---------------------- |
Expand All @@ -19,7 +19,7 @@ exports[`generate (--url-configs) basic includes the config link 1`] = `
exports[`generate (--url-configs) basic includes the config link 2`] = `
"# Description for no-foo (\`test/no-foo\`)
💼 This rule is enabled in the ✅ \`recommended\` [config](http://example.com/configs).
💼 This rule is enabled in the ✅ \`recommended\` [config](https://example.com/configs).
<!-- end auto-generated rule header -->
"
Expand All @@ -28,7 +28,7 @@ exports[`generate (--url-configs) basic includes the config link 2`] = `
exports[`generate (--url-configs) basic includes the config link 3`] = `
"# Description for no-bar (\`test/no-bar\`)
💼 This rule is enabled in the \`customConfig\` [config](http://example.com/configs).
💼 This rule is enabled in the \`customConfig\` [config](https://example.com/configs).
<!-- end auto-generated rule header -->
"
Expand All @@ -38,8 +38,8 @@ exports[`generate (--url-configs) with only recommended config includes the conf
"## Rules
<!-- begin auto-generated rules list -->
💼 [Configurations](http://example.com/configs) enabled in.\\
✅ Set in the \`recommended\` [configuration](http://example.com/configs).
💼 [Configurations](https://example.com/configs) enabled in.\\
✅ Set in the \`recommended\` [configuration](https://example.com/configs).
| Name | Description | 💼 |
| :----------------------------- | :---------------------- | :- |
Expand All @@ -52,7 +52,7 @@ exports[`generate (--url-configs) with only recommended config includes the conf
exports[`generate (--url-configs) with only recommended config includes the config link 2`] = `
"# Description for no-foo (\`test/no-foo\`)
💼 This rule is enabled in the ✅ \`recommended\` [config](http://example.com/configs).
💼 This rule is enabled in the ✅ \`recommended\` [config](https://example.com/configs).
<!-- end auto-generated rule header -->
"
Expand Down

0 comments on commit d8aa370

Please sign in to comment.