From 4877c5d1dbc1408f5681e97ebf2a47e8fb197b31 Mon Sep 17 00:00:00 2001 From: Muhammad Hammad Date: Mon, 9 Jan 2023 16:48:26 -0500 Subject: [PATCH 1/3] feat(website): link every rule to the playground with default config This change includes a link in every rule doc to the playground, clicking on the link opens the playground with default config for the rule already loaded #6085 --- .../website/plugins/generated-rule-docs.ts | 73 ++++++++++++++++--- 1 file changed, 61 insertions(+), 12 deletions(-) diff --git a/packages/website/plugins/generated-rule-docs.ts b/packages/website/plugins/generated-rule-docs.ts index 90f0b3fa6f70..c7bbc33e7d82 100644 --- a/packages/website/plugins/generated-rule-docs.ts +++ b/packages/website/plugins/generated-rule-docs.ts @@ -4,6 +4,7 @@ import * as fs from 'fs'; import type { JSONSchema7 } from 'json-schema'; import type { JSONSchema } from 'json-schema-to-typescript'; import { compile } from 'json-schema-to-typescript'; +import * as lz from 'lzstring.ts'; import type * as mdast from 'mdast'; import { EOL } from 'os'; import * as path from 'path'; @@ -193,35 +194,79 @@ export const generatedRuleDocs: Plugin = () => { type: 'paragraph', } as mdast.Paragraph); + // need this, so we don't have comments inside the JSON objects + const getEslintrcStr = (withComment: boolean): string => { + return `{ + "rules": {${ + withComment + ? '\n // Note: you must disable the base rule as it can report incorrect errors' + : '' + } + "${extendsBaseRuleName}": "off", + "@typescript-eslint/${file.stem}": "${optionLevel}" + } +}`; + }; + root.children.splice(howToUseH2Index + 1, 0, { lang: 'js', type: 'code', meta: 'title=".eslintrc.cjs"', - value: `module.exports = { - "rules": { - // Note: you must disable the base rule as it can report incorrect errors - "${extendsBaseRuleName}": "off", - "@typescript-eslint/${file.stem}": "${optionLevel}" - } -};`, + value: `module.exports = ${getEslintrcStr(true)};`, } as mdast.Code); + + root.children.splice(howToUseH2Index + 2, 0, { + children: [ + { + type: 'link', + url: `/play#eslintrc=${convertToPlaygroundHash( + getEslintrcStr(false), + )}`, + children: [ + { + type: 'text', + value: 'Click here to try this rule in the playground', + }, + ], + }, + ], + type: 'paragraph', + } as mdast.Paragraph); } else { // For non-extended rules, the code snippet is placed before the first h2 // (i.e. at the end of the initial explanation) const firstH2Index = root.children.findIndex( child => nodeIsHeading(child) && child.depth === 2, ); + + const eslintrcStr = `{ + "rules": { + "@typescript-eslint/${file.stem}": "${optionLevel}" + } +}`; root.children.splice(firstH2Index, 0, { lang: 'js', type: 'code', meta: 'title=".eslintrc.cjs"', - value: `module.exports = { - "rules": { - "@typescript-eslint/${file.stem}": "${optionLevel}" - } -};`, + value: `module.exports = ${eslintrcStr};`, } as mdast.Code); + root.children.splice(firstH2Index + 1, 0, { + children: [ + { + type: 'link', + url: `/play#eslintrc=${convertToPlaygroundHash(eslintrcStr)}`, + children: [ + { + type: 'text', + value: 'Click here to try this rule in the playground', + }, + ], + }, + ], + type: 'paragraph', + } as mdast.Paragraph); + if (meta.schema.length === 0) { root.children.splice(optionsH2Index + 1, 0, { children: [ @@ -395,6 +440,10 @@ export const generatedRuleDocs: Plugin = () => { }; }; +function convertToPlaygroundHash(eslintrc: string): string { + return lz.LZString.compressToEncodedURIComponent(eslintrc); +} + function nodeIsHeading(node: unist.Node): node is mdast.Heading { return node.type === 'heading'; } From 2ad6f6f2b0ae536a019de4f91ca88c015a353852 Mon Sep 17 00:00:00 2001 From: Muhammad Hammad Date: Sun, 22 Jan 2023 15:56:42 -0500 Subject: [PATCH 2/3] feat(website): link every rule to the playground with default config, pr changes Changes: 1) Renamed functions and variables to use full work string instead of str 2) Added jsdoc with better explanation for functions 3) Created a new MDXComponent for try in playground link 4) Some formatting and text fixes #6085 --- .../website/plugins/generated-rule-docs.ts | 53 +++++++------------ .../MDXComponents/TryInPlayground.module.css | 3 ++ .../theme/MDXComponents/TryInPlayground.tsx | 21 ++++++++ .../website/src/theme/MDXComponents/index.tsx | 2 + 4 files changed, 44 insertions(+), 35 deletions(-) create mode 100644 packages/website/src/theme/MDXComponents/TryInPlayground.module.css create mode 100644 packages/website/src/theme/MDXComponents/TryInPlayground.tsx diff --git a/packages/website/plugins/generated-rule-docs.ts b/packages/website/plugins/generated-rule-docs.ts index c7bbc33e7d82..d29d240c91fc 100644 --- a/packages/website/plugins/generated-rule-docs.ts +++ b/packages/website/plugins/generated-rule-docs.ts @@ -194,8 +194,11 @@ export const generatedRuleDocs: Plugin = () => { type: 'paragraph', } as mdast.Paragraph); - // need this, so we don't have comments inside the JSON objects - const getEslintrcStr = (withComment: boolean): string => { + /** + * @param withComment Whether to include a full comment note. + * @remarks `withComment` can't be used inside a JSON object which is needed for eslintrc in the playground + */ + const getEslintrcString = (withComment: boolean): string => { return `{ "rules": {${ withComment @@ -212,26 +215,15 @@ export const generatedRuleDocs: Plugin = () => { lang: 'js', type: 'code', meta: 'title=".eslintrc.cjs"', - value: `module.exports = ${getEslintrcStr(true)};`, + value: `module.exports = ${getEslintrcString(true)};`, } as mdast.Code); root.children.splice(howToUseH2Index + 2, 0, { - children: [ - { - type: 'link', - url: `/play#eslintrc=${convertToPlaygroundHash( - getEslintrcStr(false), - )}`, - children: [ - { - type: 'text', - value: 'Click here to try this rule in the playground', - }, - ], - }, - ], - type: 'paragraph', - } as mdast.Paragraph); + value: ``, + type: 'jsx', + } as unist.Node); } else { // For non-extended rules, the code snippet is placed before the first h2 // (i.e. at the end of the initial explanation) @@ -239,7 +231,7 @@ export const generatedRuleDocs: Plugin = () => { child => nodeIsHeading(child) && child.depth === 2, ); - const eslintrcStr = `{ + const getEslintrcString = `{ "rules": { "@typescript-eslint/${file.stem}": "${optionLevel}" } @@ -248,24 +240,15 @@ export const generatedRuleDocs: Plugin = () => { lang: 'js', type: 'code', meta: 'title=".eslintrc.cjs"', - value: `module.exports = ${eslintrcStr};`, + value: `module.exports = ${getEslintrcString};`, } as mdast.Code); root.children.splice(firstH2Index + 1, 0, { - children: [ - { - type: 'link', - url: `/play#eslintrc=${convertToPlaygroundHash(eslintrcStr)}`, - children: [ - { - type: 'text', - value: 'Click here to try this rule in the playground', - }, - ], - }, - ], - type: 'paragraph', - } as mdast.Paragraph); + value: ``, + type: 'jsx', + } as unist.Node); if (meta.schema.length === 0) { root.children.splice(optionsH2Index + 1, 0, { diff --git a/packages/website/src/theme/MDXComponents/TryInPlayground.module.css b/packages/website/src/theme/MDXComponents/TryInPlayground.module.css new file mode 100644 index 000000000000..2830e4da6ec0 --- /dev/null +++ b/packages/website/src/theme/MDXComponents/TryInPlayground.module.css @@ -0,0 +1,3 @@ +.tryInPlaygroundLink { + float: right; +} diff --git a/packages/website/src/theme/MDXComponents/TryInPlayground.tsx b/packages/website/src/theme/MDXComponents/TryInPlayground.tsx new file mode 100644 index 000000000000..98e63560edaf --- /dev/null +++ b/packages/website/src/theme/MDXComponents/TryInPlayground.tsx @@ -0,0 +1,21 @@ +import React from 'react'; + +import styles from './TryInPlayground.module.css'; + +export function TryInPlayground({ + eslintrcHash, +}: { + eslintrcHash: string; +}): React.ReactNode { + return ( +
+ + Try this rule in the playground ↗ + +
+
+ ); +} diff --git a/packages/website/src/theme/MDXComponents/index.tsx b/packages/website/src/theme/MDXComponents/index.tsx index 70fa555536b5..c810e8b72833 100644 --- a/packages/website/src/theme/MDXComponents/index.tsx +++ b/packages/website/src/theme/MDXComponents/index.tsx @@ -1,9 +1,11 @@ import MDXComponents from '@theme-original/MDXComponents'; import { RuleAttributes } from './RuleAttributes'; +import { TryInPlayground } from './TryInPlayground'; // eslint-disable-next-line import/no-default-export export default { ...MDXComponents, 'rule-attributes': RuleAttributes, + 'try-in-playground': TryInPlayground, }; From e96e5b613dc3373dd5d214046bad5cb149cd1927 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Tue, 7 Feb 2023 20:44:36 -0500 Subject: [PATCH 3/3] lil touchups --- .../src/theme/MDXComponents/TryInPlayground.tsx | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/website/src/theme/MDXComponents/TryInPlayground.tsx b/packages/website/src/theme/MDXComponents/TryInPlayground.tsx index 98e63560edaf..d9b096f1d909 100644 --- a/packages/website/src/theme/MDXComponents/TryInPlayground.tsx +++ b/packages/website/src/theme/MDXComponents/TryInPlayground.tsx @@ -8,14 +8,12 @@ export function TryInPlayground({ eslintrcHash: string; }): React.ReactNode { return ( - + + Try this rule in the playground ↗ + ); }