eslint-doc-generator
Advanced tools
Comparing version 0.24.0 to 0.25.0
@@ -63,2 +63,3 @@ import { Command, Argument, Option } from 'commander'; | ||
urlConfigs: { type: 'string' }, | ||
urlRuleDoc: { type: 'string' }, | ||
}; | ||
@@ -109,2 +110,3 @@ const schema = { | ||
.option('--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) { | ||
@@ -111,0 +113,0 @@ // Load config file options and merge with CLI options. |
@@ -75,2 +75,3 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'; | ||
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. | ||
@@ -121,3 +122,3 @@ const details = Object.entries(plugin.rules) | ||
// Regenerate the header (title/notices) of each rule doc. | ||
const newHeaderLines = generateRuleHeaderLines(description, name, plugin, configsToRules, pluginPrefix, configEmojis, ignoreConfig, ruleDocNotices, ruleDocTitleFormat, urlConfigs); | ||
const newHeaderLines = generateRuleHeaderLines(description, name, plugin, configsToRules, pluginPrefix, configEmojis, ignoreConfig, ruleDocNotices, ruleDocTitleFormat, urlConfigs, urlRuleDoc); | ||
const contents = readFileSync(pathToDoc).toString(); | ||
@@ -159,3 +160,3 @@ const contentsNew = replaceOrCreateHeader(contents, newHeaderLines, END_RULE_HEADER_MARKER); | ||
const readmeContents = readFileSync(pathToReadme, 'utf8'); | ||
const readmeContentsNew = updateRulesList(details, readmeContents, plugin, configsToRules, pluginPrefix, pathRuleDoc, pathToReadme, path, configEmojis, ignoreConfig, ruleListColumns, urlConfigs, splitBy); | ||
const readmeContentsNew = updateRulesList(details, readmeContents, plugin, configsToRules, pluginPrefix, pathRuleDoc, pathToReadme, path, configEmojis, ignoreConfig, ruleListColumns, urlConfigs, urlRuleDoc, splitBy); | ||
if (check) { | ||
@@ -162,0 +163,0 @@ if (readmeContentsNew !== readmeContents) { |
@@ -24,3 +24,4 @@ import { RuleDocTitleFormat } from './rule-doc-title-format.js'; | ||
SPLIT_BY = "splitBy", | ||
URL_CONFIGS = "urlConfigs" | ||
URL_CONFIGS = "urlConfigs", | ||
URL_RULE_DOC = "urlRuleDoc" | ||
} | ||
@@ -43,2 +44,3 @@ export declare const OPTION_DEFAULTS: { | ||
urlConfigs: undefined; | ||
urlRuleDoc: undefined; | ||
}; | ||
@@ -61,2 +63,3 @@ export type GenerateOptions = { | ||
urlConfigs?: string; | ||
urlRuleDoc?: string; | ||
}; |
@@ -47,2 +47,3 @@ import { COLUMN_TYPE, NOTICE_TYPE } from './types.js'; | ||
OPTION_TYPE["URL_CONFIGS"] = "urlConfigs"; | ||
OPTION_TYPE["URL_RULE_DOC"] = "urlRuleDoc"; | ||
})(OPTION_TYPE || (OPTION_TYPE = {})); | ||
@@ -72,3 +73,4 @@ const DEFAULT_RULE_DOC_TITLE_FORMAT = 'desc-parens-prefix-name'; // Using this variable ensures this default has the correct type (not just a plain string). | ||
[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 is used to ensure all options are included, but without losing type information. |
import { COLUMN_TYPE } from './types.js'; | ||
import type { Plugin, RuleDetails, ConfigsToRules, ConfigEmojis } from './types.js'; | ||
export declare function updateRulesList(details: RuleDetails[], markdown: string, plugin: Plugin, configsToRules: ConfigsToRules, pluginPrefix: string, pathRuleDoc: string, pathToReadme: string, pathToPlugin: string, configEmojis: ConfigEmojis, ignoreConfig: string[], ruleListColumns: COLUMN_TYPE[], urlConfigs?: string, splitBy?: string): string; | ||
export declare function updateRulesList(details: RuleDetails[], markdown: string, plugin: Plugin, configsToRules: ConfigsToRules, pluginPrefix: string, pathRuleDoc: string, pathToReadme: string, pathToPlugin: string, configEmojis: ConfigEmojis, ignoreConfig: string[], ruleListColumns: COLUMN_TYPE[], urlConfigs?: string, urlRuleDoc?: string, splitBy?: string): string; |
@@ -64,3 +64,3 @@ import { BEGIN_RULE_LIST_MARKER, END_RULE_LIST_MARKER } from './markers.js'; | ||
} | ||
function buildRuleRow(columnsEnabled, rule, configsToRules, pluginPrefix, pathRuleDoc, configEmojis, ignoreConfig) { | ||
function buildRuleRow(columnsEnabled, rule, configsToRules, pluginPrefix, pathRuleDoc, configEmojis, ignoreConfig, urlRuleDoc) { | ||
const columns = { | ||
@@ -78,3 +78,3 @@ // Alphabetical order. | ||
: '', | ||
[COLUMN_TYPE.NAME]: `[${rule.name}](${pathRuleDoc.replace(/{name}/g, rule.name)})`, | ||
[COLUMN_TYPE.NAME]: `[${rule.name}](${(urlRuleDoc ?? pathRuleDoc).replace(/{name}/g, rule.name)})`, | ||
[COLUMN_TYPE.OPTIONS]: hasOptions(rule.schema) ? EMOJI_OPTIONS : '', | ||
@@ -91,3 +91,3 @@ [COLUMN_TYPE.REQUIRES_TYPE_CHECKING]: rule.requiresTypeChecking | ||
} | ||
function generateRulesListMarkdown(columns, details, configsToRules, pluginPrefix, pathRuleDoc, configEmojis, ignoreConfig) { | ||
function generateRulesListMarkdown(columns, details, configsToRules, pluginPrefix, pathRuleDoc, configEmojis, ignoreConfig, urlRuleDoc) { | ||
const listHeaderRow = Object.entries(columns).flatMap(([columnType, enabled]) => { | ||
@@ -108,3 +108,3 @@ if (!enabled) { | ||
.sort(({ name: a }, { name: b }) => a.toLowerCase().localeCompare(b.toLowerCase())) | ||
.map((rule) => buildRuleRow(columns, rule, configsToRules, pluginPrefix, pathRuleDoc, configEmojis, ignoreConfig)), | ||
.map((rule) => buildRuleRow(columns, rule, configsToRules, pluginPrefix, pathRuleDoc, configEmojis, ignoreConfig, urlRuleDoc)), | ||
], { align: 'l' } // Left-align headers. | ||
@@ -116,3 +116,3 @@ ); | ||
*/ | ||
function generateRulesListMarkdownWithSplitBy(columns, details, plugin, configsToRules, pluginPrefix, pathRuleDoc, configEmojis, ignoreConfig, splitBy) { | ||
function generateRulesListMarkdownWithSplitBy(columns, details, plugin, configsToRules, pluginPrefix, pathRuleDoc, configEmojis, ignoreConfig, splitBy, urlRuleDoc) { | ||
const values = new Set(details.map((detail) => getPropertyFromRule(plugin, detail.name, splitBy))); | ||
@@ -137,3 +137,3 @@ // Common values for boolean properties. | ||
const rulesForThisValue = details.filter((detail) => DISABLED_VALUES.has(getPropertyFromRule(plugin, detail.name, splitBy))); | ||
parts.push(generateRulesListMarkdown(columns, rulesForThisValue, configsToRules, pluginPrefix, pathRuleDoc, configEmojis, ignoreConfig)); | ||
parts.push(generateRulesListMarkdown(columns, rulesForThisValue, configsToRules, pluginPrefix, pathRuleDoc, configEmojis, ignoreConfig, urlRuleDoc)); | ||
} | ||
@@ -153,7 +153,7 @@ // For each possible non-disabled value, show a header and list of corresponding rules. | ||
: splitByFinalPart; | ||
parts.push(`### ${ENABLED_VALUES.has(value) ? splitByTitle : value}`, generateRulesListMarkdown(columns, rulesForThisValue, configsToRules, pluginPrefix, pathRuleDoc, configEmojis, ignoreConfig)); | ||
parts.push(`### ${ENABLED_VALUES.has(value) ? splitByTitle : value}`, generateRulesListMarkdown(columns, rulesForThisValue, configsToRules, pluginPrefix, pathRuleDoc, configEmojis, ignoreConfig, urlRuleDoc)); | ||
} | ||
return parts.join('\n\n'); | ||
} | ||
export function updateRulesList(details, markdown, plugin, configsToRules, pluginPrefix, pathRuleDoc, pathToReadme, pathToPlugin, configEmojis, ignoreConfig, ruleListColumns, urlConfigs, splitBy) { | ||
export function updateRulesList(details, markdown, plugin, configsToRules, pluginPrefix, pathRuleDoc, pathToReadme, pathToPlugin, configEmojis, ignoreConfig, ruleListColumns, urlConfigs, urlRuleDoc, splitBy) { | ||
let listStartIndex = markdown.indexOf(BEGIN_RULE_LIST_MARKER); | ||
@@ -189,6 +189,6 @@ let listEndIndex = markdown.indexOf(END_RULE_LIST_MARKER); | ||
const list = splitBy | ||
? generateRulesListMarkdownWithSplitBy(columns, details, plugin, configsToRules, pluginPrefix, pathRuleDoc, configEmojis, ignoreConfig, splitBy) | ||
: generateRulesListMarkdown(columns, details, configsToRules, pluginPrefix, pathRuleDoc, configEmojis, ignoreConfig); | ||
? generateRulesListMarkdownWithSplitBy(columns, details, plugin, configsToRules, pluginPrefix, pathRuleDoc, configEmojis, ignoreConfig, splitBy, urlRuleDoc) | ||
: generateRulesListMarkdown(columns, details, configsToRules, pluginPrefix, pathRuleDoc, configEmojis, ignoreConfig, urlRuleDoc); | ||
const newContent = `${legend ? `${legend}\n\n` : ''}${list}`; | ||
return `${preList}${BEGIN_RULE_LIST_MARKER}\n\n${newContent}\n\n${END_RULE_LIST_MARKER}${postList}`; | ||
} |
@@ -7,2 +7,2 @@ import { Plugin, ConfigsToRules, ConfigEmojis, NOTICE_TYPE } from './types.js'; | ||
*/ | ||
export declare function generateRuleHeaderLines(description: string | undefined, name: string, plugin: Plugin, configsToRules: ConfigsToRules, pluginPrefix: string, configEmojis: ConfigEmojis, ignoreConfig: string[], ruleDocNotices: NOTICE_TYPE[], ruleDocTitleFormat: RuleDocTitleFormat, urlConfigs?: string): string; | ||
export declare function generateRuleHeaderLines(description: string | undefined, name: string, plugin: Plugin, configsToRules: ConfigsToRules, pluginPrefix: string, configEmojis: ConfigEmojis, ignoreConfig: string[], ruleDocNotices: NOTICE_TYPE[], ruleDocTitleFormat: RuleDocTitleFormat, urlConfigs?: string, urlRuleDoc?: string): string; |
@@ -77,3 +77,3 @@ import { END_RULE_HEADER_MARKER } from './markers.js'; | ||
// 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. | ||
@@ -84,3 +84,3 @@ const slashesInCurrentRuleName = ruleName.match(/\//g); | ||
return `${EMOJI_DEPRECATED} This rule is deprecated.${replacedBy && replacedBy.length > 0 | ||
? ` It was replaced by ${ruleNamesToList(replacedBy, pluginPrefix, relativePathToRuleDocRoot)}.` | ||
? ` It was replaced by ${ruleNamesToList(replacedBy, pluginPrefix, relativePathToRuleDocRoot, urlRuleDoc)}.` | ||
: ''}`; | ||
@@ -117,3 +117,3 @@ }, | ||
*/ | ||
function ruleNamesToList(ruleNames, pluginPrefix, relativePathToRuleDocRoot) { | ||
function ruleNamesToList(ruleNames, pluginPrefix, relativePathToRuleDocRoot, urlRuleDoc) { | ||
return ruleNames | ||
@@ -126,3 +126,5 @@ .map((ruleName) => { | ||
: ruleName; | ||
return `[\`${ruleNameWithoutPluginPrefix}\`](${relativePathToRuleDocRoot + ruleNameWithoutPluginPrefix}.md)`; | ||
return `[\`${ruleNameWithoutPluginPrefix}\`](${urlRuleDoc | ||
? urlRuleDoc.replace(/{name}/g, ruleName) | ||
: `${relativePathToRuleDocRoot + ruleNameWithoutPluginPrefix}.md`})`; | ||
}) | ||
@@ -155,3 +157,3 @@ .join(', '); | ||
*/ | ||
function getRuleNoticeLines(ruleName, plugin, configsToRules, pluginPrefix, configEmojis, ignoreConfig, ruleDocNotices, urlConfigs) { | ||
function getRuleNoticeLines(ruleName, plugin, configsToRules, pluginPrefix, configEmojis, ignoreConfig, ruleDocNotices, urlConfigs, urlRuleDoc) { | ||
const lines = []; | ||
@@ -199,3 +201,4 @@ const rule = plugin.rules?.[ruleName]; | ||
pluginPrefix, | ||
type: rule.meta?.type, // Convert union type to enum. | ||
type: rule.meta?.type, | ||
urlRuleDoc, | ||
}) | ||
@@ -256,6 +259,6 @@ : ruleNoticeStrOrFn); | ||
*/ | ||
export function generateRuleHeaderLines(description, name, plugin, configsToRules, pluginPrefix, configEmojis, ignoreConfig, ruleDocNotices, ruleDocTitleFormat, urlConfigs) { | ||
export function generateRuleHeaderLines(description, name, plugin, configsToRules, pluginPrefix, configEmojis, ignoreConfig, ruleDocNotices, ruleDocTitleFormat, urlConfigs, urlRuleDoc) { | ||
return [ | ||
makeTitle(name, description, pluginPrefix, ruleDocTitleFormat), | ||
...getRuleNoticeLines(name, plugin, configsToRules, pluginPrefix, configEmojis, ignoreConfig, ruleDocNotices, urlConfigs), | ||
...getRuleNoticeLines(name, plugin, configsToRules, pluginPrefix, configEmojis, ignoreConfig, ruleDocNotices, urlConfigs, urlRuleDoc), | ||
'', | ||
@@ -262,0 +265,0 @@ END_RULE_HEADER_MARKER, |
{ | ||
"name": "eslint-doc-generator", | ||
"version": "0.24.0", | ||
"version": "0.25.0", | ||
"description": "Automatic documentation generator for ESLint plugins and rules.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -138,2 +138,3 @@ # eslint-doc-generator | ||
| `--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. | | ||
@@ -140,0 +141,0 @@ ### `--rule-doc-title-format` |
101266
1840
202