diff --git a/packages/website/package.json b/packages/website/package.json index ee01833b0077..a9fc31f238f8 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -60,6 +60,7 @@ "cross-fetch": "*", "history": "^4.9.0", "make-dir": "*", + "mdast-util-from-markdown": "^2.0.1", "mdast-util-mdx": "^3.0.0", "monaco-editor": "~0.50.0", "raw-loader": "^4.0.2", diff --git a/packages/website/plugins/generated-rule-docs/RuleDocsPage.ts b/packages/website/plugins/generated-rule-docs/RuleDocsPage.ts index e540c014b133..3c44aae99a0c 100644 --- a/packages/website/plugins/generated-rule-docs/RuleDocsPage.ts +++ b/packages/website/plugins/generated-rule-docs/RuleDocsPage.ts @@ -1,4 +1,5 @@ import type { ESLintPluginRuleModule } from '@typescript-eslint/eslint-plugin/use-at-your-own-risk/rules'; +import { fromMarkdown } from 'mdast-util-from-markdown'; import type * as unist from 'unist'; import type { VFileWithStem } from '../utils/rules'; @@ -57,9 +58,15 @@ export class RuleDocsPage { spliceChildren( start: number, deleteCount: number, - ...items: unist.Node[] + ...items: (string | unist.Node)[] ): void { - this.#children.splice(start, deleteCount, ...items); + this.#children.splice( + start, + deleteCount, + ...items.map(item => + typeof item === 'string' ? fromMarkdown(item) : item, + ), + ); this.#headingIndices = this.#recreateHeadingIndices(); } diff --git a/packages/website/plugins/generated-rule-docs/index.ts b/packages/website/plugins/generated-rule-docs/index.ts index f29c0371748b..85c425cb38e4 100644 --- a/packages/website/plugins/generated-rule-docs/index.ts +++ b/packages/website/plugins/generated-rule-docs/index.ts @@ -6,7 +6,6 @@ import { isESLintPluginRuleModule, isVFileWithStem } from '../utils/rules'; import { addESLintHashToCodeBlocksMeta } from './addESLintHashToCodeBlocksMeta'; import { createRuleDocsPage } from './createRuleDocsPage'; import { insertBaseRuleReferences } from './insertions/insertBaseRuleReferences'; -import { insertFormattingNotice } from './insertions/insertFormattingNotice'; import { insertNewRuleReferences } from './insertions/insertNewRuleReferences'; import { insertResources } from './insertions/insertResources'; import { insertRuleDescription } from './insertions/insertRuleDescription'; @@ -28,7 +27,6 @@ export const generatedRuleDocs: Plugin = () => { removeSourceCodeNotice(page); insertRuleDescription(page); - insertFormattingNotice(page); const eslintrc = rule.meta.docs.extendsBaseRule ? insertBaseRuleReferences(page) diff --git a/packages/website/plugins/generated-rule-docs/insertions/insertBaseRuleReferences.ts b/packages/website/plugins/generated-rule-docs/insertions/insertBaseRuleReferences.ts index f88a17a85bc6..b5c1f5604f7e 100644 --- a/packages/website/plugins/generated-rule-docs/insertions/insertBaseRuleReferences.ts +++ b/packages/website/plugins/generated-rule-docs/insertions/insertBaseRuleReferences.ts @@ -10,33 +10,11 @@ export function insertBaseRuleReferences(page: RuleDocsPage): string { ? page.rule.meta.docs.extendsBaseRule : page.file.stem; - page.spliceChildren(page.headingIndices.options + 1, 0, { - children: [ - { - value: 'See ', - type: 'text', - }, - { - children: [ - { - type: 'inlineCode', - value: `eslint/${extendsBaseRuleName}`, - }, - { - type: 'text', - value: ' options', - }, - ], - type: 'link', - url: `https://eslint.org/docs/rules/${extendsBaseRuleName}#options`, - }, - { - type: 'text', - value: '.', - }, - ], - type: 'paragraph', - } as mdast.Paragraph); + page.spliceChildren( + page.headingIndices.options + 1, + 0, + `See [\`eslint/${extendsBaseRuleName}\`'s options](https://eslint.org/docs/rules/${extendsBaseRuleName}#options).`, + ); const eslintrc = getEslintrcString( extendsBaseRuleName, diff --git a/packages/website/plugins/generated-rule-docs/insertions/insertFormattingNotice.ts b/packages/website/plugins/generated-rule-docs/insertions/insertFormattingNotice.ts deleted file mode 100644 index a4ff96e120e8..000000000000 --- a/packages/website/plugins/generated-rule-docs/insertions/insertFormattingNotice.ts +++ /dev/null @@ -1,100 +0,0 @@ -import type { MdxJsxFlowElement } from 'mdast-util-mdx'; - -import type { RuleDocsPage } from '../RuleDocsPage'; - -export function insertFormattingNotice(page: RuleDocsPage): void { - const replacement = page.rule.meta.replacedBy?.find(e => - e.startsWith('@stylistic/'), - ); - if (!replacement) { - return; - } - - const url = - replacement && - `https://eslint.style/rules/${replacement.replace('@stylistic/', '')}`; - - page.spliceChildren(0, 0, { - children: [ - { - type: 'paragraph', - children: [ - { - type: 'text', - value: 'Formatting rules now live in ', - }, - { - type: 'link', - title: null, - url: 'https://eslint.style', - children: [ - { - type: 'text', - value: 'eslint-stylistic', - }, - ], - }, - { - type: 'text', - value: '. ', - }, - ...(url - ? [ - { - type: 'link', - title: null, - url, - children: [ - { - type: 'text', - value: replacement, - }, - ], - }, - { - type: 'text', - value: ' is the replacement for this rule. ', - }, - ] - : []), - { - type: 'break', - }, - { - type: 'text', - value: 'See ', - }, - { - type: 'link', - title: null, - url: '/blog/deprecating-formatting-rules', - children: [ - { - type: 'text', - value: 'Deprecating Formatting Rules', - }, - ], - }, - { - type: 'text', - value: ' for more information.', - }, - ], - }, - ], - attributes: [ - { - type: 'mdxJsxAttribute', - name: 'title', - value: 'Deprecated', - }, - { - type: 'mdxJsxAttribute', - name: 'type', - value: 'danger', - }, - ], - name: 'Admonition', - type: 'mdxJsxFlowElement', - } as MdxJsxFlowElement); -} diff --git a/packages/website/plugins/generated-rule-docs/insertions/insertNewRuleReferences.ts b/packages/website/plugins/generated-rule-docs/insertions/insertNewRuleReferences.ts index 5b601124ef35..08cca0d8e0d3 100644 --- a/packages/website/plugins/generated-rule-docs/insertions/insertNewRuleReferences.ts +++ b/packages/website/plugins/generated-rule-docs/insertions/insertNewRuleReferences.ts @@ -1,6 +1,7 @@ import { EOL } from 'node:os'; import * as path from 'node:path'; +import type { ESLintPluginDocs } from '@typescript-eslint/eslint-plugin/use-at-your-own-risk/rules'; import { compile } from '@typescript-eslint/rule-schema-to-typescript-types'; import type * as mdast from 'mdast'; import type { MdxJsxFlowElement } from 'mdast-util-mdx'; @@ -62,12 +63,9 @@ export async function insertNewRuleReferences( page.spliceChildren( firstH2Index, 0, - { - lang: 'js', - type: 'code', - meta: 'title=".eslintrc.cjs"', - value: `module.exports = ${eslintrc};`, - } as mdast.Code, + `\`\`\`js title=".eslintrc.cjs" +module.exports = ${eslintrc}; +\`\`\``, { attributes: [ { @@ -97,46 +95,18 @@ export async function insertNewRuleReferences( : Object.keys(page.rule.meta.schema).length === 0; if (hasNoConfig) { - page.spliceChildren(page.headingIndices.options + 1, 0, { - children: [ - { - type: 'text', - value: 'This rule is not configurable.', - }, - ], - type: 'paragraph', - } as mdast.Paragraph); + page.spliceChildren( + page.headingIndices.options + 1, + 0, + 'This rule is not configurable.', + ); } else if (!COMPLICATED_RULE_OPTIONS.has(page.file.stem)) { page.spliceChildren( page.headingIndices.options + 1, 0, - { - children: - typeof page.rule.meta.docs.recommended === 'object' - ? [ - { - type: 'text', - value: - 'This rule accepts the following options, and has more strict settings in the ', - } as mdast.Text, - ...linkToConfigs( - page.rule.meta.docs.requiresTypeChecking - ? ['strict', 'strict-type-checked'] - : ['strict'], - ), - { - type: 'text', - value: ` config${page.rule.meta.docs.requiresTypeChecking ? 's' : ''}.`, - } as mdast.Text, - ] - : [ - { - type: 'text', - value: 'This rule accepts the following options:', - } as mdast.Text, - ], - type: 'paragraph', - } as mdast.Paragraph, + typeof page.rule.meta.docs.recommended === 'object' + ? linkToConfigsForObject(page.rule.meta.docs) + : 'This rule accepts the following options:', { lang: 'ts', type: 'code', @@ -156,30 +126,14 @@ export async function insertNewRuleReferences( return eslintrc; } -function linkToConfigs(configs: string[]): mdast.Node[] { - const links = configs.map( - (config): mdast.Link => ({ - children: [ - { - type: 'inlineCode', - value: config, - } as mdast.InlineCode, - ], - type: 'link', - url: `/users/configs#${config}`, - }), - ); - - return links.length === 1 - ? links - : [ - links[0], - { - type: 'text', - value: ' and ', - } as mdast.Text, - links[1], - ]; +function linkToConfigsForObject(docs: ESLintPluginDocs): string { + return [ + 'This rule accepts the following options, and has more strict settings in the', + (docs.requiresTypeChecking ? ['strict', 'strict-type-checked'] : ['strict']) + .map(config => `[${config}](/users/configs#${config})`) + .join(' and '), + `config${docs.requiresTypeChecking ? 's' : ''}.`, + ].join(' '); } function getRuleDefaultOptions(page: RuleDocsPage): string { diff --git a/packages/website/plugins/generated-rule-docs/insertions/insertResources.ts b/packages/website/plugins/generated-rule-docs/insertions/insertResources.ts index 50efedf8a71c..e6b6eb88f096 100644 --- a/packages/website/plugins/generated-rule-docs/insertions/insertResources.ts +++ b/packages/website/plugins/generated-rule-docs/insertions/insertResources.ts @@ -1,4 +1,3 @@ -import type * as mdast from 'mdast'; import type { MdxJsxFlowElement } from 'mdast-util-mdx'; import { getUrlForRuleTest, sourceUrlPrefix } from '../../utils/rules'; @@ -9,61 +8,11 @@ export function insertResources(page: RuleDocsPage): void { page.spliceChildren( page.children.length, 0, - { - children: [ - { - type: 'text', - value: 'Resources', - }, - ], - depth: 2, - type: 'heading', - } as mdast.Heading, - { - children: [ - { - children: [ - { - children: [ - { - type: 'link', - url: `${sourceUrlPrefix}src/rules/${page.file.stem}.ts`, - children: [ - { - type: 'text', - value: 'Rule source', - }, - ], - }, - ], - type: 'paragraph', - }, - ], - type: 'listItem', - }, - { - children: [ - { - children: [ - { - type: 'link', - url: getUrlForRuleTest(page.file.stem), - children: [ - { - type: 'text', - value: 'Test source', - }, - ], - }, - ], - type: 'paragraph', - }, - ], - type: 'listItem', - }, - ], - type: 'list', - } as mdast.List, + `## Resources + +- [Rule source](${sourceUrlPrefix}src/rules/${page.file.stem}.ts) +- [Test source](${getUrlForRuleTest(page.file.stem)}) + `, ); // Also add a notice about coming from ESLint core for extension rules diff --git a/packages/website/plugins/generated-rule-docs/insertions/insertRuleDescription.ts b/packages/website/plugins/generated-rule-docs/insertions/insertRuleDescription.ts index 86d0be107d30..832c35b60264 100644 --- a/packages/website/plugins/generated-rule-docs/insertions/insertRuleDescription.ts +++ b/packages/website/plugins/generated-rule-docs/insertions/insertRuleDescription.ts @@ -1,36 +1,17 @@ -import type * as mdast from 'mdast'; import type { MdxJsxFlowElement } from 'mdast-util-mdx'; import type { RuleDocsPage } from '../RuleDocsPage'; export function insertRuleDescription(page: RuleDocsPage): void { - page.spliceChildren( - 0, - 0, - { - children: [ - { - children: page.rule.meta.docs.description - .split(/`(.+?)`/) - .map((value, index, array) => ({ - type: index % 2 === 0 ? 'text' : 'inlineCode', - value: index === array.length - 1 ? `${value}.` : value, - })), - type: 'paragraph', - }, - ], - type: 'blockquote', - } as mdast.Blockquote, - { - attributes: [ - { - type: 'mdxJsxAttribute', - name: 'name', - value: page.file.stem, - }, - ], - name: 'RuleAttributes', - type: 'mdxJsxFlowElement', - } as MdxJsxFlowElement, - ); + page.spliceChildren(0, 0, `> ${page.rule.meta.docs.description}.`, { + attributes: [ + { + type: 'mdxJsxAttribute', + name: 'name', + value: page.file.stem, + }, + ], + name: 'RuleAttributes', + type: 'mdxJsxFlowElement', + } as MdxJsxFlowElement); } diff --git a/packages/website/plugins/generated-rule-docs/insertions/insertWhenNotToUseIt.ts b/packages/website/plugins/generated-rule-docs/insertions/insertWhenNotToUseIt.ts index 7365438bde60..97f03abe2061 100644 --- a/packages/website/plugins/generated-rule-docs/insertions/insertWhenNotToUseIt.ts +++ b/packages/website/plugins/generated-rule-docs/insertions/insertWhenNotToUseIt.ts @@ -1,5 +1,3 @@ -import type * as mdast from 'mdast'; - import { nodeIsHeading } from '../../utils/nodes'; import type { RuleDocsPage } from '../RuleDocsPage'; @@ -23,48 +21,8 @@ export function insertWhenNotToUseIt(page: RuleDocsPage): void { page.spliceChildren( nextHeadingIndex === -1 ? page.children.length : nextHeadingIndex - 1, 0, - { - children: [ - ...(hasExistingText ? [{ type: 'thematicBreak' }] : []), - { - type: 'text', - value: - 'Type checked lint rules are more powerful than traditional lint rules, but also require configuring ', - }, - { - type: 'link', - title: null, - url: `/getting-started/typed-linting`, - children: [ - { - type: 'text', - value: 'type checked linting', - }, - ], - }, - { - type: 'text', - value: '. See ', - }, - { - type: 'link', - title: null, - url: `/troubleshooting/typed-linting/performance`, - children: [ - { - type: 'text', - value: - 'Troubleshooting > Linting with Type Information > Performance', - }, - ], - }, - { - type: 'text', - value: - ' if you experience performance degredations after enabling type checked rules.', - }, - ], - type: 'paragraph', - } as mdast.Paragraph, + ...(hasExistingText ? ['---'] : []), + 'Type checked lint rules are more powerful than traditional lint rules, but also require configuring [type checked linting](/getting-started/typed-linting).', + 'See [Troubleshooting > Linting with Type Information > Performance](/troubleshooting/typed-linting/performance) if you experience performance degredations after enabling type checked rules.', ); } diff --git a/yarn.lock b/yarn.lock index 3b6a9df17e32..2156ce651c3f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14055,7 +14055,7 @@ __metadata: languageName: node linkType: hard -"mdast-util-from-markdown@npm:^2.0.0": +"mdast-util-from-markdown@npm:^2.0.0, mdast-util-from-markdown@npm:^2.0.1": version: 2.0.1 resolution: "mdast-util-from-markdown@npm:2.0.1" dependencies: @@ -20268,6 +20268,7 @@ __metadata: konamimojisplosion: ^0.5.2 lz-string: ^1.5.0 make-dir: "*" + mdast-util-from-markdown: ^2.0.1 mdast-util-mdx: ^3.0.0 monaco-editor: ~0.50.0 prettier: ^3.2.5