Skip to content

Commit

Permalink
fix: only apply prettier formatting to affected doc content
Browse files Browse the repository at this point in the history
  • Loading branch information
bmish committed Oct 3, 2022
1 parent 6f3c7ea commit 47b6ad8
Show file tree
Hide file tree
Showing 9 changed files with 617 additions and 158 deletions.
8 changes: 8 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ module.exports = {
},
},
rules: {
// TODO: these import rules are running extremely slowly (several seconds each) so disable for now.
'import/default': 'off',
'import/namespace': 'off',
'import/no-cycle': 'off',
'import/no-deprecated': 'off',
'import/no-named-as-default': 'off',
'import/no-named-as-default-member': 'off',

'import/extensions': ['error', 'always'],
'node/no-missing-import': 'off', // Disabled due to a bug: https://github.com/mysticatea/eslint-plugin-node/issues/342
'unicorn/no-array-reduce': 'off',
Expand Down
30 changes: 17 additions & 13 deletions lib/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ import { loadPlugin, getPluginPrefix } from './package-json.js';
import { updateRulesList } from './rule-list.js';
import { generateRuleHeaderLines } from './rule-notices.js';
import { END_RULE_HEADER_MARKER } from './markers.js';
import {
findSectionHeader,
format,
replaceOrCreateHeader,
} from './markdown.js';
import { findSectionHeader, replaceOrCreateHeader } from './markdown.js';
import type { RuleModule, RuleDetails } from './types.js';

/**
Expand Down Expand Up @@ -94,9 +90,6 @@ export async function generate(path: string) {
continue;
}

const contents = readFileSync(pathToDoc).toString();
const lines = contents.split('\n');

// Regenerate the header (title/notices) of each rule doc.
const newHeaderLines = generateRuleHeaderLines(
description,
Expand All @@ -105,9 +98,15 @@ export async function generate(path: string) {
pluginPrefix
);

replaceOrCreateHeader(lines, newHeaderLines, END_RULE_HEADER_MARKER);
const contents = readFileSync(pathToDoc).toString();
const contentsNew = await replaceOrCreateHeader(
contents,
newHeaderLines,
END_RULE_HEADER_MARKER,
pathToDoc
);

writeFileSync(pathToDoc, await format(lines.join('\n'), pathToDoc));
writeFileSync(pathToDoc, contentsNew);

// Check for potential issues with the rule doc.

Expand All @@ -124,7 +123,12 @@ export async function generate(path: string) {
}

// Update the rules list in the README.
let readme = readFileSync(pathTo.readme, 'utf8');
readme = updateRulesList(details, readme, plugin, pluginPrefix);
writeFileSync(pathTo.readme, await format(readme, pathTo.readme), 'utf8');
const readme = await updateRulesList(
details,
readFileSync(pathTo.readme, 'utf8'),
plugin,
pluginPrefix,
pathTo.readme
);
writeFileSync(pathTo.readme, readme, 'utf8');
}
21 changes: 13 additions & 8 deletions lib/markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,29 @@ export async function format(str: string, filePath: string): Promise<string> {
/**
* Replace the header of a doc up to and including the specified marker.
* Insert at beginning if header doesn't exist.
* @param lines - lines of doc
* @param newHeaderLines - lines of new header including marker
* @param markdown - doc content
* @param newHeader - new header including marker
* @param marker - marker to indicate end of header
*/
export function replaceOrCreateHeader(
lines: string[],
newHeaderLines: string[],
marker: string
export async function replaceOrCreateHeader(
markdown: string,
newHeader: string,
marker: string,
pathToDoc: string
) {
const lines = markdown.split('\n');

const markerLineIndex = lines.indexOf(marker);

if (markerLineIndex === -1 && lines.length > 0 && lines[0].startsWith('# ')) {
// No marker present so delete any existing title before we add the new one.
lines.splice(0, 1);
}

// Replace header section (or create at top if missing).
lines.splice(0, markerLineIndex + 1, ...newHeaderLines);
return (
(await format(newHeader, pathToDoc)) +
lines.slice(markerLineIndex + 1).join('\n')
);
}

/**
Expand Down
33 changes: 13 additions & 20 deletions lib/rule-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
EMOJI_CONFIGS,
} from './emojis.js';
import { hasCustomConfigs } from './configs.js';
import { findSectionHeader } from './markdown.js';
import { findSectionHeader, format } from './markdown.js';
import type { Plugin, RuleDetails } from './types.js';

function getConfigurationColumnValueForRule(
Expand Down Expand Up @@ -93,12 +93,13 @@ function generateRulesListMarkdown(
.join('\n');
}

export function updateRulesList(
export async function updateRulesList(
details: RuleDetails[],
markdown: string,
plugin: Plugin,
pluginPrefix: string
): string {
pluginPrefix: string,
pathToReadme: string
): Promise<string> {
let listStartIndex = markdown.indexOf(BEGIN_RULE_LIST_MARKER);
let listEndIndex = markdown.indexOf(END_RULE_LIST_MARKER);

Expand All @@ -116,7 +117,7 @@ export function updateRulesList(
) {
// If the markers are missing, we'll try to find the rules section and insert the list there.
listStartIndex = rulesSectionIndex + rulesSectionHeader.length;
listEndIndex = rulesSectionIndex + rulesSectionHeader.length;
listEndIndex = rulesSectionIndex + rulesSectionHeader.length - 1;
} else {
// Account for length of pre-existing marker.
listEndIndex += END_RULE_LIST_MARKER.length;
Expand All @@ -128,22 +129,14 @@ export function updateRulesList(
);
}

return [
// Doc before rule list marker.
markdown.slice(0, Math.max(0, listStartIndex - 1)),
const preList = markdown.slice(0, Math.max(0, listStartIndex));
const postList = markdown.slice(Math.max(0, listEndIndex));

// New begin marker.
BEGIN_RULE_LIST_MARKER,
'',

// New rule list.
// New rule list.
const list = await format(
generateRulesListMarkdown(details, plugin, pluginPrefix),
'',

// New end marker.
END_RULE_LIST_MARKER,
pathToReadme
);

// Doc after rule list marker.
markdown.slice(Math.max(0, listEndIndex)),
].join('\n');
return `${preList}${BEGIN_RULE_LIST_MARKER}\n\n${list}\n${END_RULE_LIST_MARKER}${postList}`;
}
6 changes: 3 additions & 3 deletions lib/rule-notices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,20 +118,20 @@ function removeTrailingPeriod(str: string) {
* Generate a rule doc header for a particular rule.
* @param description - rule description
* @param name - rule name
* @returns {string[]} - lines for new header including marker
* @returns {string} - new header including marker
*/
export function generateRuleHeaderLines(
description: string,
name: string,
plugin: Plugin,
pluginPrefix: string
): string[] {
): string {
const descriptionFormatted = removeTrailingPeriod(
toSentenceCase(description)
);
return [
`# ${descriptionFormatted} (\`${pluginPrefix}/${name}\`)`,
...getRuleNoticeLines(name, plugin, pluginPrefix),
END_RULE_HEADER_MARKER,
];
].join('\n');
}
75 changes: 11 additions & 64 deletions test/lib/__snapshots__/generator-test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ exports[`generator #generate No configs found does not crash 1`] = `
| ------------------------------ | ------------- | --- | --- | --- |
| [no-foo](docs/rules/no-foo.md) | disallow foo. | | | |
<!-- end rules list -->
"
<!-- end rules list -->"
`;

exports[`generator #generate No configs found does not crash 2`] = `
Expand All @@ -32,7 +31,6 @@ exports[`generator #generate README missing rule list markers but with rules sec
Foo.
## Rules
<!-- begin rules list -->
| Rule | Description | ✅ | 🔧 | 💡 |
Expand All @@ -45,8 +43,7 @@ Old rules list.
## Other
Bar.
"
Bar."
`;

exports[`generator #generate Rule description needs to be formatted capitalizes the first letter and removes the trailing period from the description 1`] = `
Expand All @@ -73,8 +70,7 @@ exports[`generator #generate adds extra column to rules table for TypeScript rul
| [no-bar](docs/rules/no-bar.md) | Description of no-bar. | | | | 💭 |
| [no-foo](docs/rules/no-foo.md) | Description of no-foo. | | | | |
<!-- end rules list -->
"
<!-- end rules list -->"
`;

exports[`generator #generate deprecated rule with no rule doc nor meta.docs updates the documentation 1`] = `
Expand All @@ -84,8 +80,7 @@ exports[`generator #generate deprecated rule with no rule doc nor meta.docs upda
| ------------------------------ | ----------- | --- | --- | --- |
| [no-foo](docs/rules/no-foo.md) | | ❌ | | |
<!-- end rules list -->
"
<!-- end rules list -->"
`;

exports[`generator #generate deprecated rules updates the documentation 1`] = `
Expand All @@ -97,8 +92,7 @@ exports[`generator #generate deprecated rules updates the documentation 1`] = `
| [no-baz](docs/rules/no-baz.md) | Description. | ❌ | | |
| [no-foo](docs/rules/no-foo.md) | Description. | ❌ | | |
<!-- end rules list -->
"
<!-- end rules list -->"
`;

exports[`generator #generate deprecated rules updates the documentation 2`] = `
Expand Down Expand Up @@ -135,8 +129,7 @@ exports[`generator #generate only a \`recommended\` config updates the documenta
| ------------------------------ | ------------ | --- | --- | --- |
| [no-foo](docs/rules/no-foo.md) | Description. | ✅ | | |
<!-- end rules list -->
"
<!-- end rules list -->"
`;

exports[`generator #generate only a \`recommended\` config updates the documentation 2`] = `
Expand All @@ -154,22 +147,15 @@ exports[`generator #generate rule doc without header marker but pre-existing hea
✅ This rule is enabled in the \`recommended\` config.
<!-- end rule header -->
Pre-existing notice about the rule being recommended.
## Rule details
Details.
"
Details."
`;

exports[`generator #generate successful updates the documentation 1`] = `
"# eslint-plugin-test
Description.
## Rules
<!-- begin rules list -->
| Rule | Description | 💼 | 🔧 | 💡 |
Expand All @@ -179,9 +165,7 @@ Description.
| [no-foo](docs/rules/no-foo.md) | Description of no-foo. | ✅ | 🔧 | 💡 |
<!-- end rules list -->
more content.
"
more content."
`;

exports[`generator #generate successful updates the documentation 2`] = `
Expand All @@ -194,17 +178,11 @@ exports[`generator #generate successful updates the documentation 2`] = `
💡 This rule provides [suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions) that can be applied manually.
<!-- end rule header -->
## Rule details
details
## Options
optionToDoSomething1 - explanation
optionToDoSomething2 - explanation
Long line that SHOULD NOT get wrapped due to prettier proseWrap config. Long line that SHOULD NOT get wrapped due to prettier proseWrap config.
"
optionToDoSomething2 - explanation"
`;

exports[`generator #generate successful updates the documentation 3`] = `
Expand All @@ -215,45 +193,14 @@ exports[`generator #generate successful updates the documentation 3`] = `
🔧 This rule is automatically fixable using the \`--fix\` [option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) on the command line.
<!-- end rule header -->
## Rule details
details
"
details"
`;

exports[`generator #generate successful updates the documentation 4`] = `
"# Description of no-boz (\`test/no-baz\`)
<!-- end rule header -->
## Rule details
details
"
`;

exports[`generator #generate uses prettier config from package.json updates the documentation 1`] = `
"<!-- begin rules list -->
| Rule | Description | ✅ | 🔧 | 💡 |
| ------------------------------ | ---------------------- | --- | --- | --- |
| [no-foo](docs/rules/no-foo.md) | Description of no-foo. | | | |
<!-- end rules list -->
"
`;

exports[`generator #generate uses prettier config from package.json updates the documentation 2`] = `
"# Description of no-foo (\`test/no-foo\`)
💼 This rule is enabled in the following configs: \`all\`.
<!-- end rule header -->
## Rule details
details Long line that SHOULD get wrapped due to prettier proseWrap config. Long
line that SHOULD get wrapped due to prettier proseWrap config.
"
details"
`;
Loading

0 comments on commit 47b6ad8

Please sign in to comment.