From 7b69687edc619a9b3a605dceff4d421291de7432 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Mon, 30 May 2022 13:45:08 +0800 Subject: [PATCH 1/6] docs: avoid using diff code blocks --- docs/linting/MONOREPO.md | 32 +++++++++---------- docs/linting/README.md | 55 +++++++++++++++++---------------- docs/linting/TROUBLESHOOTING.md | 15 +++++---- docs/linting/TYPED_LINTING.md | 33 +++++++++++--------- 4 files changed, 71 insertions(+), 64 deletions(-) diff --git a/docs/linting/MONOREPO.md b/docs/linting/MONOREPO.md index 2f8cbe15f349..a9df44c6844c 100644 --- a/docs/linting/MONOREPO.md +++ b/docs/linting/MONOREPO.md @@ -18,22 +18,22 @@ Earlier in our docs on [typed linting](./TYPED_LINTING.md), we showed you how to For example, this is how we specify all of our `tsconfig.json` within this repo. -```diff title=".eslintrc.js" - module.exports = { - root: true, - parser: '@typescript-eslint/parser', - parserOptions: { - tsconfigRootDir: __dirname, -- project: ['./tsconfig.json'], -+ project: ['./tsconfig.eslint.json', './packages/*/tsconfig.json'], - }, - plugins: ['@typescript-eslint'], - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:@typescript-eslint/recommended-requiring-type-checking', - ], - }; +```js title=".eslintrc.js" +module.exports = { + root: true, + parser: '@typescript-eslint/parser', + parserOptions: { + tsconfigRootDir: __dirname, + // highlight-next-line + project: ['./tsconfig.eslint.json', './packages/*/tsconfig.json'], + }, + plugins: ['@typescript-eslint'], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:@typescript-eslint/recommended-requiring-type-checking', + ], +}; ``` If you're looking for an example of what the `.eslintrc.js`, and referenced `tsconfig.json` might look like in a real example, look no further than this very repo. We're a multi-package monorepo that uses one `tsconfig.json` per package, that also uses typed linting. diff --git a/docs/linting/README.md b/docs/linting/README.md index dbf08d1e7808..629d7a59c551 100644 --- a/docs/linting/README.md +++ b/docs/linting/README.md @@ -136,19 +136,18 @@ If you use [`prettier`](https://www.npmjs.com/package/prettier), there is also a Using this config by adding it to the end of your `extends`: -```diff title=".eslintrc.js" - module.exports = { - root: true, - parser: '@typescript-eslint/parser', - plugins: [ - '@typescript-eslint', - ], - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', -+ 'prettier', - ], - }; +```js title=".eslintrc.js" +module.exports = { + root: true, + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint'], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + // highlight-next-line + 'prettier', + ], +}; ``` ### Community Configs @@ -196,20 +195,22 @@ Below are just a few examples: Every plugin that is out there includes documentation on the various configurations and rules they offer. A typical plugin might be used like: -```diff title=".eslintrc.js" - module.exports = { - root: true, - parser: '@typescript-eslint/parser', - plugins: [ - '@typescript-eslint', -+ 'jest', - ], - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', -+ 'plugin:jest/recommended', - ], - }; +```js title=".eslintrc.js" +module.exports = { + root: true, + parser: '@typescript-eslint/parser', + plugins: [ + '@typescript-eslint', + // highlight-next-line + 'jest', + ], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + // highlight-next-line + 'plugin:jest/recommended', + ], +}; ``` diff --git a/docs/linting/TROUBLESHOOTING.md b/docs/linting/TROUBLESHOOTING.md index d6cb97486f57..e9e8340715c4 100644 --- a/docs/linting/TROUBLESHOOTING.md +++ b/docs/linting/TROUBLESHOOTING.md @@ -42,12 +42,15 @@ See our docs on [type aware linting](./TYPED_LINTING.md#i-get-errors-telling-me- You can use `parserOptions.extraFileExtensions` to specify an array of non-TypeScript extensions to allow, for example: -```diff - parserOptions: { - tsconfigRootDir: __dirname, - project: ['./tsconfig.json'], -+ extraFileExtensions: ['.vue'], - }, +```js title=".eslintrc.js" +module.exports = { + parserOptions: { + tsconfigRootDir: __dirname, + project: ['./tsconfig.json'], + // highlight-next-line + extraFileExtensions: ['.vue'], + }, +}; ``` ## One of my lint rules isn't working correctly on a pure JavaScript file diff --git a/docs/linting/TYPED_LINTING.md b/docs/linting/TYPED_LINTING.md index 376a0334c174..c02edb74e65f 100644 --- a/docs/linting/TYPED_LINTING.md +++ b/docs/linting/TYPED_LINTING.md @@ -8,21 +8,24 @@ Under the hood, the typescript-eslint parser uses TypeScript's compiler APIs to To tap into TypeScript's additional powers, there are two small changes you need to make to your config file: -```diff title=".eslintrc.js" - module.exports = { - root: true, - parser: '@typescript-eslint/parser', -+ parserOptions: { -+ tsconfigRootDir: __dirname, -+ project: ['./tsconfig.json'], -+ }, - plugins: ['@typescript-eslint'], - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', -+ 'plugin:@typescript-eslint/recommended-requiring-type-checking', - ], - }; +```js title=".eslintrc.js" +module.exports = { + root: true, + parser: '@typescript-eslint/parser', + // highlight-start + parserOptions: { + tsconfigRootDir: __dirname, + project: ['./tsconfig.json'], + }, + // highlight-end + plugins: ['@typescript-eslint'], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + // highlight-next-line + 'plugin:@typescript-eslint/recommended-requiring-type-checking', + ], +}; ``` In more detail: From 67a3778b2fa6ccdc7a95518b65850aefada85ed7 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Tue, 31 May 2022 14:52:29 +0800 Subject: [PATCH 2/6] refactor: attempt CSS solution --- docs/linting/MONOREPO.md | 4 +++- docs/linting/README.md | 33 ++++++++++++++------------- docs/linting/TROUBLESHOOTING.md | 2 +- docs/linting/TYPED_LINTING.md | 6 ++--- packages/website/docusaurus.config.js | 17 ++++++++++++++ packages/website/src/css/custom.css | 33 +++++++++++++++++++++++++++ 6 files changed, 74 insertions(+), 21 deletions(-) diff --git a/docs/linting/MONOREPO.md b/docs/linting/MONOREPO.md index a9df44c6844c..4ec2df161362 100644 --- a/docs/linting/MONOREPO.md +++ b/docs/linting/MONOREPO.md @@ -24,7 +24,9 @@ module.exports = { parser: '@typescript-eslint/parser', parserOptions: { tsconfigRootDir: __dirname, - // highlight-next-line + // Remove this line + project: ['./tsconfig.json'], + // Add this line project: ['./tsconfig.eslint.json', './packages/*/tsconfig.json'], }, plugins: ['@typescript-eslint'], diff --git a/docs/linting/README.md b/docs/linting/README.md index 629d7a59c551..23f0a2b1981a 100644 --- a/docs/linting/README.md +++ b/docs/linting/README.md @@ -144,7 +144,7 @@ module.exports = { extends: [ 'eslint:recommended', 'plugin:@typescript-eslint/recommended', - // highlight-next-line + // Add this line 'prettier', ], }; @@ -162,19 +162,20 @@ A few popular all-in-one configs are: To use one of these complete config packages, you would replace the `extends` with the package name. For example: -```diff title=".eslintrc.js" - module.exports = { - root: true, - parser: '@typescript-eslint/parser', - plugins: [ - '@typescript-eslint', - ], - extends: [ -- 'eslint:recommended', -- 'plugin:@typescript-eslint/recommended', -+ 'airbnb-typescript', - ], - }; +```js title=".eslintrc.js" +module.exports = { + root: true, + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint'], + extends: [ + // Removed lines start + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + // Removed lines end + // Add this line + 'airbnb-typescript', + ], +}; ``` @@ -201,13 +202,13 @@ module.exports = { parser: '@typescript-eslint/parser', plugins: [ '@typescript-eslint', - // highlight-next-line + // Add this line 'jest', ], extends: [ 'eslint:recommended', 'plugin:@typescript-eslint/recommended', - // highlight-next-line + // Add this line 'plugin:jest/recommended', ], }; diff --git a/docs/linting/TROUBLESHOOTING.md b/docs/linting/TROUBLESHOOTING.md index e9e8340715c4..d9c447b4d0e2 100644 --- a/docs/linting/TROUBLESHOOTING.md +++ b/docs/linting/TROUBLESHOOTING.md @@ -47,7 +47,7 @@ module.exports = { parserOptions: { tsconfigRootDir: __dirname, project: ['./tsconfig.json'], - // highlight-next-line + // Add this line extraFileExtensions: ['.vue'], }, }; diff --git a/docs/linting/TYPED_LINTING.md b/docs/linting/TYPED_LINTING.md index c02edb74e65f..ae58028e442b 100644 --- a/docs/linting/TYPED_LINTING.md +++ b/docs/linting/TYPED_LINTING.md @@ -12,17 +12,17 @@ To tap into TypeScript's additional powers, there are two small changes you need module.exports = { root: true, parser: '@typescript-eslint/parser', - // highlight-start + // Added lines start parserOptions: { tsconfigRootDir: __dirname, project: ['./tsconfig.json'], }, - // highlight-end + // Added lines end plugins: ['@typescript-eslint'], extends: [ 'eslint:recommended', 'plugin:@typescript-eslint/recommended', - // highlight-next-line + // Add this line 'plugin:@typescript-eslint/recommended-requiring-type-checking', ], }; diff --git a/packages/website/docusaurus.config.js b/packages/website/docusaurus.config.js index a06a8e0367dc..3fe2e682613d 100644 --- a/packages/website/docusaurus.config.js +++ b/packages/website/docusaurus.config.js @@ -158,6 +158,23 @@ const config = { styles: [], }, additionalLanguages: ['ignore'], + magicComments: [ + { + className: 'theme-code-block-highlighted-line', + line: 'highlight-next-line', + block: { start: 'highlight-start', end: 'highlight-end' }, + }, + { + className: 'code-block-removed-line', + line: 'Remove this line', + block: { start: 'Removed lines start', end: 'Removed lines end' }, + }, + { + className: 'code-block-added-line', + line: 'Add this line', + block: { start: 'Added lines start', end: 'Added lines end' }, + }, + ], }, tableOfContents: { maxHeadingLevel: 4, diff --git a/packages/website/src/css/custom.css b/packages/website/src/css/custom.css index b1e23a6dcd33..459bf8831beb 100644 --- a/packages/website/src/css/custom.css +++ b/packages/website/src/css/custom.css @@ -108,3 +108,36 @@ h6 { .myLineDecoration { background-color: var(--code-line-decoration); } + +.code-block-removed-line::before { + content: '-'; + display: inline-block; + width: 0px; + color: red; +} + +.code-block-removed-line { + background-color: #ff000020; + display: block; + margin: 0 calc(-1 * var(--ifm-pre-padding)); + padding: 0 var(--ifm-pre-padding); + user-select: none; +} + +.code-block-added-line::before { + content: '+'; + display: inline-block; + width: 0px; + color: rgb(2, 164, 113); +} + +.code-block-added-line { + background-color: #00ff9540; + display: block; + margin: 0 calc(-1 * var(--ifm-pre-padding)); + padding: 0 var(--ifm-pre-padding); +} + +[data-theme='dark'] .code-block-added-line { + background-color: #00ff9510; +} From 114d6ba1eb6dac2f7c21ea7f7ca0490d6e0b8377 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Tue, 31 May 2022 15:15:42 +0800 Subject: [PATCH 3/6] make copy button more functional --- packages/website/package.json | 1 + .../src/theme/CodeBlock/Content/String.tsx | 121 ++++++++++++++++++ .../theme/CodeBlock/Content/styles.module.css | 81 ++++++++++++ 3 files changed, 203 insertions(+) create mode 100644 packages/website/src/theme/CodeBlock/Content/String.tsx create mode 100644 packages/website/src/theme/CodeBlock/Content/styles.module.css diff --git a/packages/website/package.json b/packages/website/package.json index 2eaf1c0d1c92..cceccb2b6f56 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -26,6 +26,7 @@ "json5": "^2.2.1", "konamimojisplosion": "^0.5.1", "lzstring.ts": "^2.0.2", + "prism-react-renderer": "^1.3.3", "react": "^18.1.0", "react-dom": "^18.1.0", "remark-docusaurus-tabs": "^0.2.0", diff --git a/packages/website/src/theme/CodeBlock/Content/String.tsx b/packages/website/src/theme/CodeBlock/Content/String.tsx new file mode 100644 index 000000000000..a6a1601313eb --- /dev/null +++ b/packages/website/src/theme/CodeBlock/Content/String.tsx @@ -0,0 +1,121 @@ +// Change: added `copiedCode` which filters out the removed lines + +import React from 'react'; +import clsx from 'clsx'; +import { + useThemeConfig, + parseCodeBlockTitle, + parseLanguage, + parseLines, + containsLineNumbers, + usePrismTheme, + useCodeWordWrap, +} from '@docusaurus/theme-common'; +import Highlight, { defaultProps, type Language } from 'prism-react-renderer'; +import Line from '@theme/CodeBlock/Line'; +import CopyButton from '@theme/CodeBlock/CopyButton'; +import WordWrapButton from '@theme/CodeBlock/WordWrapButton'; +import Container from '@theme/CodeBlock/Container'; +import type { Props } from '@theme/CodeBlock/Content/String'; + +import styles from './styles.module.css'; + +// eslint-disable-next-line import/no-default-export +export default function CodeBlockString({ + children, + className: blockClassName = '', + metastring, + title: titleProp, + showLineNumbers: showLineNumbersProp, + language: languageProp, +}: Props): JSX.Element { + const { + prism: { defaultLanguage, magicComments }, + } = useThemeConfig(); + const language = + languageProp ?? parseLanguage(blockClassName) ?? defaultLanguage; + const prismTheme = usePrismTheme(); + const wordWrap = useCodeWordWrap(); + + // We still parse the metastring in case we want to support more syntax in the + // future. Note that MDX doesn't strip quotes when parsing metastring: + // "title=\"xyz\"" => title: "\"xyz\"" + const title = parseCodeBlockTitle(metastring) || titleProp; + + const { lineClassNames, code } = parseLines(children, { + metastring, + language, + magicComments, + }); + const showLineNumbers = + showLineNumbersProp ?? containsLineNumbers(metastring); + + const copiedCode = code + .split('\n') + .filter((c, i) => !lineClassNames[i]?.includes('code-block-removed-line')) + .join('\n'); + + return ( + + {title &&
{title}
} +
+ + {({ + className, + tokens, + getLineProps, + getTokenProps, + }): JSX.Element => ( +
+              
+                {tokens.map((line, i) => (
+                  
+                ))}
+              
+            
+ )} +
+
+ {(wordWrap.isEnabled || wordWrap.isCodeScrollable) && ( + wordWrap.toggle()} + isEnabled={wordWrap.isEnabled} + /> + )} + +
+
+
+ ); +} diff --git a/packages/website/src/theme/CodeBlock/Content/styles.module.css b/packages/website/src/theme/CodeBlock/Content/styles.module.css new file mode 100644 index 000000000000..e75d80399a67 --- /dev/null +++ b/packages/website/src/theme/CodeBlock/Content/styles.module.css @@ -0,0 +1,81 @@ +/* No change; copied over so that the .tsx file can get its CSS */ + +.codeBlockContent { + position: relative; + /* rtl:ignore */ + direction: ltr; + border-radius: inherit; +} + +.codeBlockTitle { + border-bottom: 1px solid var(--ifm-color-emphasis-300); + font-size: var(--ifm-code-font-size); + font-weight: 500; + padding: 0.75rem var(--ifm-pre-padding); + border-top-left-radius: inherit; + border-top-right-radius: inherit; +} + +.codeBlock { + --ifm-pre-background: var(--prism-background-color); + margin: 0; + padding: 0; +} + +.codeBlockTitle + .codeBlockContent .codeBlock { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.codeBlockStandalone { + padding: 0; +} + +.codeBlockLines { + font: inherit; + /* rtl:ignore */ + float: left; + min-width: 100%; + padding: var(--ifm-pre-padding); +} + +.codeBlockLinesWithNumbering { + display: table; + padding: var(--ifm-pre-padding) 0; +} + +@media print { + .codeBlockLines { + white-space: pre-wrap; + } +} + +.buttonGroup { + display: flex; + column-gap: 0.2rem; + position: absolute; + right: calc(var(--ifm-pre-padding) / 2); + top: calc(var(--ifm-pre-padding) / 2); +} + +.buttonGroup button { + display: flex; + align-items: center; + background: var(--prism-background-color); + color: var(--prism-color); + border: 1px solid var(--ifm-color-emphasis-300); + border-radius: var(--ifm-global-radius); + padding: 0.4rem; + line-height: 0; + transition: opacity 200ms ease-in-out; + opacity: 0; +} + +.buttonGroup button:focus-visible, +.buttonGroup button:hover { + opacity: 1 !important; +} + +:global(.theme-code-block:hover) .buttonGroup button { + opacity: 0.4; +} From a49c0cc54cecc34f1b4bc06866c36e8e1e079f3b Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Tue, 31 May 2022 15:53:03 +0800 Subject: [PATCH 4/6] fix cspell --- .cspell.json | 1 + packages/website/src/theme/CodeBlock/Content/String.tsx | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.cspell.json b/.cspell.json index 09466a9d300a..f8b231053454 100644 --- a/.cspell.json +++ b/.cspell.json @@ -73,6 +73,7 @@ "linebreaks", "lzstring", "markdownlint", + "metastring", "necroing", "nocheck", "nullish", diff --git a/packages/website/src/theme/CodeBlock/Content/String.tsx b/packages/website/src/theme/CodeBlock/Content/String.tsx index a6a1601313eb..3ae728a137ea 100644 --- a/packages/website/src/theme/CodeBlock/Content/String.tsx +++ b/packages/website/src/theme/CodeBlock/Content/String.tsx @@ -80,7 +80,6 @@ export default function CodeBlockString({ getTokenProps, }): JSX.Element => (
Date: Tue, 31 May 2022 16:01:49 +0800
Subject: [PATCH 5/6] leave more space

---
 packages/website/src/css/custom.css | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/packages/website/src/css/custom.css b/packages/website/src/css/custom.css
index 459bf8831beb..dcda800b7ab7 100644
--- a/packages/website/src/css/custom.css
+++ b/packages/website/src/css/custom.css
@@ -113,6 +113,8 @@ h6 {
   content: '-';
   display: inline-block;
   width: 0px;
+  position: relative;
+  left: -0.7em;
   color: red;
 }
 
@@ -128,6 +130,8 @@ h6 {
   content: '+';
   display: inline-block;
   width: 0px;
+  position: relative;
+  left: -0.7em;
   color: rgb(2, 164, 113);
 }
 

From ff80b5375516b842ec8a1484f820e542de1e9874 Mon Sep 17 00:00:00 2001
From: Joshua Chen 
Date: Tue, 31 May 2022 16:09:26 +0800
Subject: [PATCH 6/6] fix lint again

---
 .cspell.json                                            | 1 +
 packages/website/src/theme/CodeBlock/Content/String.tsx | 1 +
 2 files changed, 2 insertions(+)

diff --git a/.cspell.json b/.cspell.json
index f8b231053454..4691cd152db3 100644
--- a/.cspell.json
+++ b/.cspell.json
@@ -76,6 +76,7 @@
     "metastring",
     "necroing",
     "nocheck",
+    "noninteractive",
     "nullish",
     "OOM",
     "OOMs",
diff --git a/packages/website/src/theme/CodeBlock/Content/String.tsx b/packages/website/src/theme/CodeBlock/Content/String.tsx
index 3ae728a137ea..f26a6ec5b9c5 100644
--- a/packages/website/src/theme/CodeBlock/Content/String.tsx
+++ b/packages/website/src/theme/CodeBlock/Content/String.tsx
@@ -80,6 +80,7 @@ export default function CodeBlockString({
             getTokenProps,
           }): JSX.Element => (