From 31a81066682f635a18dd42a8ce8efab65e06ba98 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 4 Dec 2023 16:45:49 -0500 Subject: [PATCH 1/8] RFC: Configuring File Name from Block Meta --- rfcs/configure-file-name-from-block-meta.md | 82 +++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 rfcs/configure-file-name-from-block-meta.md diff --git a/rfcs/configure-file-name-from-block-meta.md b/rfcs/configure-file-name-from-block-meta.md new file mode 100644 index 00000000..1a2ba08b --- /dev/null +++ b/rfcs/configure-file-name-from-block-meta.md @@ -0,0 +1,82 @@ +# RFC: Configuring File Name from Block Meta + +## Summary + +Allowing code blocks to change the `filename` used in `eslint-plugin-markdown`'s processor using codeblock `meta` text. + +## Motivation + +Some projects use ESLint `overrides` to run different lint rules on files based on their file name. +There's no way to respect file name based `overrides` in parsed Markdown blocks right now using `eslint-plugin-markdown`'s parsing. +This RFC would allow code blocks to specify a custom file name so that `overrides` can be used more idiomatically. + +### Real-World Example + +In [`create-typescript-app`](https://github.com/JoshuaKGoldberg/create-typescript-app), `*.json` files _except_ `package.json` files have [`jsonc/sort-keys`](https://ota-meshi.github.io/eslint-plugin-jsonc/rules/sort-keys.html) enabled using [an ESLint config file `overrides`](https://github.com/JoshuaKGoldberg/create-typescript-app/blob/76a75186fd89fc3f66e4c1254c717c28d70afe0d/.eslintrc.cjs#L94). +However, a code block in a file named `docs/FAQs.md` intended to be a `package.json` is currently given a name like `create-typescript-app/docs/FAQs.md/0_0.jsonc`. +Short of hardcoding overrides or disabling the lint rule in the file, there is no way to have the `overrides` apply to the markdown code block. + +## Detailed Design + +This RFC proposes that code blocks be allowed to specify a file path in `meta` with `title="..."`. +Doing so would replace the `filename` provided by `eslint-plugin-markdown`'s `preprocess` method. + +````md +```json title="package.json" +{} +``` +```` + +Parsing would be handled by a regular expression similar to the [Docusaurus parser](https://github.com/facebook/docusaurus/blob/7650829e913ec4bb1263d855719779f6b97066b6/packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts#L12). +The `title` meta prop name is intentionally the same as Docusaurus, so projects can use the same attribute for Docusaurus and ESLint. + +Parsed language is ignored when the codeblock provides a custom title. +Some languages have many file extensions, such as TypeScript's `.cts`, `.ts`, `.tsx`, etc. +Some extensions may map to multiple languages, such as Perl and Prolog both using `.pl`. + +Roughly: + +```diff +- filename: `${index}.${block.lang.trim().split(" ")[0]}`, ++ filename: titleFromMeta(block) ?? `${index}.${block.lang.trim().split(" ")[0]}`, +``` + +### Name Uniqueness + +Codeblocks must have unique file paths for ESLint processing. +If a codeblock has the same file path as a previously processed codeblock, processing should throw an error. + +If multiple code blocks require the same _file_ name, they can be given different _directory paths_ to ensure uniqueness: + +````md +```json title="example-1/package.json" +{} +``` + +```json title="example-2/package.json" +{} +``` +```` + +### Parsing Meta + +There is no unified standard in the ecosystem for parsing codeblock metadata in Markdown. +The syntax has roughly converged on the syntax looking like \`\`\`lang key="value", and to a lesser extent, using `title` as the prop name. + +- [Docusaurus's `codeBlockTitleRegex`](https://github.com/facebook/docusaurus/blob/7650829e913ec4bb1263d855719779f6b97066b6/packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts#L12): only supports a [code title prop](https://mdxjs.com/guides/syntax-highlighting/#syntax-highlighting-with-the-meta-field) like \`\`\`jsx title="/src/components/HelloCodeTitle.js" +- Gatsby plugins such as [`gatsby-remark-prismjs`](https://www.gatsbyjs.com/plugins/gatsby-remark-prismjs) rely on a syntax like \`\`\`javascript{numberLines: true}`. + - Separately, [`gatsby-remark-code-titles`](https://www.gatsbyjs.com/plugins/gatsby-remark-code-titles) allows a syntax like \`\`\`js:title=example-file.js. +- [`rehype-mdx-code-props`](https://github.com/remcohaszing/rehype-mdx-code-props): generally handles parsing of the raw `meta` text from the rehype AST. + It specifies syntax like \`\`\`js copy filename="awesome.js", with a suggestion of `filename` for just the file's name. + - [`remark-mdx-code-meta`](https://github.com/remcohaszing/remark-mdx-code-meta) is [referenced in the mdxjs.com `meta` docs](https://mdxjs.com/guides/syntax-highlighting/#syntax-highlighting-with-the-meta-field), but was deprecated with a notice to use `rehype-mdx-code-props` instead. + It also specified syntax like \`\`\`js copy filename="awesome.js" onUsage={props.beAwesome} {...props}. +- [`remark-fenced-props`](https://github.com/shawnbot/remark-fenced-props): A proof-of-concept that augments Remark's codeblock parsing with arbitrary MDX props, written to support [mdx-js/mdx/issues/702](https://github.com/mdx-js/mdx/issues/702). + It only specifies syntax like \`\`\`jsx live style={{border: '1px solid red'}} + +This RFC chooses `title` over alternatives such as `filename`. +`title` appears to be the closest to a "popular" choice in existing projects today. + +## Related Discussions + +See #226 for the original issue. +This RFC is intended to contain a superset of all information discussed there. From 7da2410f5bb0894503d27cff3b3b1494e4d6cb4c Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Tue, 9 Apr 2024 15:34:05 -0400 Subject: [PATCH 2/8] Sequential names, and filename over title --- rfcs/configure-file-name-from-block-meta.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/rfcs/configure-file-name-from-block-meta.md b/rfcs/configure-file-name-from-block-meta.md index 1a2ba08b..70f36dd9 100644 --- a/rfcs/configure-file-name-from-block-meta.md +++ b/rfcs/configure-file-name-from-block-meta.md @@ -44,9 +44,14 @@ Roughly: ### Name Uniqueness Codeblocks must have unique file paths for ESLint processing. -If a codeblock has the same file path as a previously processed codeblock, processing should throw an error. +If a codeblock has the same file path as a previously processed codeblock, it will have a sequentially increasing number appended before their extensions. +For example, given three blocks with the same name, would in order become: -If multiple code blocks require the same _file_ name, they can be given different _directory paths_ to ensure uniqueness: +- `example`: `example`, `example-1`, `example-2` +- `example.js`: `example.js`, `example-1.js`, `example-2.js` +- `example.test.ts`: `example.test.ts`, `example-1.test.ts`, `example-2.test.ts` + +Alternately, if multiple code blocks require the same _file_ name, developers can give different _directory paths_ to ensure uniqueness: ````md ```json title="example-1/package.json" @@ -61,7 +66,7 @@ If multiple code blocks require the same _file_ name, they can be given differen ### Parsing Meta There is no unified standard in the ecosystem for parsing codeblock metadata in Markdown. -The syntax has roughly converged on the syntax looking like \`\`\`lang key="value", and to a lesser extent, using `title` as the prop name. +The syntax has roughly converged on the syntax looking like \`\`\`lang key="value", and to a lesser extent, using `filename` as the prop name. - [Docusaurus's `codeBlockTitleRegex`](https://github.com/facebook/docusaurus/blob/7650829e913ec4bb1263d855719779f6b97066b6/packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts#L12): only supports a [code title prop](https://mdxjs.com/guides/syntax-highlighting/#syntax-highlighting-with-the-meta-field) like \`\`\`jsx title="/src/components/HelloCodeTitle.js" - Gatsby plugins such as [`gatsby-remark-prismjs`](https://www.gatsbyjs.com/plugins/gatsby-remark-prismjs) rely on a syntax like \`\`\`javascript{numberLines: true}`. @@ -73,8 +78,8 @@ The syntax has roughly converged on the syntax looking like \`\`\`lang key - [`remark-fenced-props`](https://github.com/shawnbot/remark-fenced-props): A proof-of-concept that augments Remark's codeblock parsing with arbitrary MDX props, written to support [mdx-js/mdx/issues/702](https://github.com/mdx-js/mdx/issues/702). It only specifies syntax like \`\`\`jsx live style={{border: '1px solid red'}} -This RFC chooses `title` over alternatives such as `filename`. -`title` appears to be the closest to a "popular" choice in existing projects today. +This RFC chooses `filename` over alternatives such as `title`. +`filename` appears to be the closest to a "popular" choice in existing projects today. ## Related Discussions From 86b721cddc3306e52cec4058a7ee0192fc3a6157 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Tue, 9 Apr 2024 15:39:13 -0400 Subject: [PATCH 3/8] Update the examples too --- rfcs/configure-file-name-from-block-meta.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rfcs/configure-file-name-from-block-meta.md b/rfcs/configure-file-name-from-block-meta.md index 70f36dd9..4d19341a 100644 --- a/rfcs/configure-file-name-from-block-meta.md +++ b/rfcs/configure-file-name-from-block-meta.md @@ -18,11 +18,11 @@ Short of hardcoding overrides or disabling the lint rule in the file, there is n ## Detailed Design -This RFC proposes that code blocks be allowed to specify a file path in `meta` with `title="..."`. +This RFC proposes that code blocks be allowed to specify a file path in `meta` with `filename="..."`. Doing so would replace the `filename` provided by `eslint-plugin-markdown`'s `preprocess` method. ````md -```json title="package.json" +```json filename="package.json" {} ``` ```` @@ -54,11 +54,11 @@ For example, given three blocks with the same name, would in order become: Alternately, if multiple code blocks require the same _file_ name, developers can give different _directory paths_ to ensure uniqueness: ````md -```json title="example-1/package.json" +```json filename="example-1/package.json" {} ``` -```json title="example-2/package.json" +```json filename="example-2/package.json" {} ``` ```` From a9de58fec5f304989c6e50face64c9bd192cb389 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Thu, 14 Nov 2024 09:50:42 -0500 Subject: [PATCH 4/8] PR feedback, and 'code( )block' normalization --- rfcs/configure-file-name-from-block-meta.md | 27 +++++++++++---------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/rfcs/configure-file-name-from-block-meta.md b/rfcs/configure-file-name-from-block-meta.md index 4d19341a..1b50a236 100644 --- a/rfcs/configure-file-name-from-block-meta.md +++ b/rfcs/configure-file-name-from-block-meta.md @@ -2,23 +2,23 @@ ## Summary -Allowing code blocks to change the `filename` used in `eslint-plugin-markdown`'s processor using codeblock `meta` text. +Allowing codeblocks to change the `filename` used in `eslint-plugin-markdown`'s processor using codeblock `meta` text. ## Motivation Some projects use ESLint `overrides` to run different lint rules on files based on their file name. -There's no way to respect file name based `overrides` in parsed Markdown blocks right now using `eslint-plugin-markdown`'s parsing. -This RFC would allow code blocks to specify a custom file name so that `overrides` can be used more idiomatically. +There's no way to respect file name based `overrides` in parsed Markdown codeblocks right now using `eslint-plugin-markdown`'s parsing. +This RFC would allow codeblocks to specify a custom file name so that `overrides` can be used more idiomatically. ### Real-World Example In [`create-typescript-app`](https://github.com/JoshuaKGoldberg/create-typescript-app), `*.json` files _except_ `package.json` files have [`jsonc/sort-keys`](https://ota-meshi.github.io/eslint-plugin-jsonc/rules/sort-keys.html) enabled using [an ESLint config file `overrides`](https://github.com/JoshuaKGoldberg/create-typescript-app/blob/76a75186fd89fc3f66e4c1254c717c28d70afe0d/.eslintrc.cjs#L94). -However, a code block in a file named `docs/FAQs.md` intended to be a `package.json` is currently given a name like `create-typescript-app/docs/FAQs.md/0_0.jsonc`. -Short of hardcoding overrides or disabling the lint rule in the file, there is no way to have the `overrides` apply to the markdown code block. +However, a codeblock in a file named `docs/FAQs.md` intended to be a `package.json` is currently given a name like `create-typescript-app/docs/FAQs.md/0_0.jsonc`. +Short of hardcoding overrides or disabling the lint rule in the file, there is no way to have the `overrides` apply to the markdown codeblock. ## Detailed Design -This RFC proposes that code blocks be allowed to specify a file path in `meta` with `filename="..."`. +This RFC proposes that codeblocks be allowed to specify a file path in `meta` (the \`\`\` opening fence) with `filename="..."`. Doing so would replace the `filename` provided by `eslint-plugin-markdown`'s `preprocess` method. ````md @@ -28,7 +28,6 @@ Doing so would replace the `filename` provided by `eslint-plugin-markdown`'s `pr ```` Parsing would be handled by a regular expression similar to the [Docusaurus parser](https://github.com/facebook/docusaurus/blob/7650829e913ec4bb1263d855719779f6b97066b6/packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts#L12). -The `title` meta prop name is intentionally the same as Docusaurus, so projects can use the same attribute for Docusaurus and ESLint. Parsed language is ignored when the codeblock provides a custom title. Some languages have many file extensions, such as TypeScript's `.cts`, `.ts`, `.tsx`, etc. @@ -44,14 +43,13 @@ Roughly: ### Name Uniqueness Codeblocks must have unique file paths for ESLint processing. -If a codeblock has the same file path as a previously processed codeblock, it will have a sequentially increasing number appended before their extensions. -For example, given three blocks with the same name, would in order become: +[ESLint internally prepends a unique number to codeblock filenames](https://github.com/eslint/eslint/blob/5ff6c1dd09f32b56c05ab97f328741fc8ffb1f64/lib/services/processor-service.js#L83), in the format of \`${i}_${block.filename}\`. +For example, given three codeblocks with the same name, the names in order would become: -- `example`: `example`, `example-1`, `example-2` -- `example.js`: `example.js`, `example-1.js`, `example-2.js` -- `example.test.ts`: `example.test.ts`, `example-1.test.ts`, `example-2.test.ts` +- `example`: `0_example`, `1_example`, `2_example` +- `example.js`: `0_example.js`, `1_example.js`, `2_example.js` -Alternately, if multiple code blocks require the same _file_ name, developers can give different _directory paths_ to ensure uniqueness: +Alternately, if multiple codeblocks require the same _file_ name, developers can give different _directory paths_: ````md ```json filename="example-1/package.json" @@ -78,8 +76,11 @@ The syntax has roughly converged on the syntax looking like \`\`\`lang key - [`remark-fenced-props`](https://github.com/shawnbot/remark-fenced-props): A proof-of-concept that augments Remark's codeblock parsing with arbitrary MDX props, written to support [mdx-js/mdx/issues/702](https://github.com/mdx-js/mdx/issues/702). It only specifies syntax like \`\`\`jsx live style={{border: '1px solid red'}} +#### `filename` or `title` + This RFC chooses `filename` over alternatives such as `title`. `filename` appears to be the closest to a "popular" choice in existing projects today. +As noted in [docusaurus/discussions#10033 Choice of filename vs. title for codeblocks](https://github.com/facebook/docusaurus/discussions/10033), `filename` implies a source code file names, whereas `title` implies the visual display. ## Related Discussions From ac14f2a83c8f8f45f2dc075eca740012422911e2 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Thu, 14 Nov 2024 09:53:44 -0500 Subject: [PATCH 5/8] Also mention Expressive Code --- rfcs/configure-file-name-from-block-meta.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/rfcs/configure-file-name-from-block-meta.md b/rfcs/configure-file-name-from-block-meta.md index 1b50a236..c392506e 100644 --- a/rfcs/configure-file-name-from-block-meta.md +++ b/rfcs/configure-file-name-from-block-meta.md @@ -66,7 +66,8 @@ Alternately, if multiple codeblocks require the same _file_ name, developers can There is no unified standard in the ecosystem for parsing codeblock metadata in Markdown. The syntax has roughly converged on the syntax looking like \`\`\`lang key="value", and to a lesser extent, using `filename` as the prop name. -- [Docusaurus's `codeBlockTitleRegex`](https://github.com/facebook/docusaurus/blob/7650829e913ec4bb1263d855719779f6b97066b6/packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts#L12): only supports a [code title prop](https://mdxjs.com/guides/syntax-highlighting/#syntax-highlighting-with-the-meta-field) like \`\`\`jsx title="/src/components/HelloCodeTitle.js" +- [Docusaurus's `codeBlockTitleRegex`](https://github.com/facebook/docusaurus/blob/7650829e913ec4bb1263d855719779f6b97066b6/packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts#L12): only supports a [code title prop](https://mdxjs.com/guides/syntax-highlighting/#syntax-highlighting-with-the-meta-field) like \`\`\`jsx title="/src/components/HelloCodeTitle.js". +- [Expressive Code's `title`](https://expressive-code.com/key-features/code-component/#title): used by [Astro](https://astro.build), with the syntax \`\`\`js title="my-test-file.js". - Gatsby plugins such as [`gatsby-remark-prismjs`](https://www.gatsbyjs.com/plugins/gatsby-remark-prismjs) rely on a syntax like \`\`\`javascript{numberLines: true}`. - Separately, [`gatsby-remark-code-titles`](https://www.gatsbyjs.com/plugins/gatsby-remark-code-titles) allows a syntax like \`\`\`js:title=example-file.js. - [`rehype-mdx-code-props`](https://github.com/remcohaszing/rehype-mdx-code-props): generally handles parsing of the raw `meta` text from the rehype AST. @@ -74,9 +75,7 @@ The syntax has roughly converged on the syntax looking like \`\`\`lang key - [`remark-mdx-code-meta`](https://github.com/remcohaszing/remark-mdx-code-meta) is [referenced in the mdxjs.com `meta` docs](https://mdxjs.com/guides/syntax-highlighting/#syntax-highlighting-with-the-meta-field), but was deprecated with a notice to use `rehype-mdx-code-props` instead. It also specified syntax like \`\`\`js copy filename="awesome.js" onUsage={props.beAwesome} {...props}. - [`remark-fenced-props`](https://github.com/shawnbot/remark-fenced-props): A proof-of-concept that augments Remark's codeblock parsing with arbitrary MDX props, written to support [mdx-js/mdx/issues/702](https://github.com/mdx-js/mdx/issues/702). - It only specifies syntax like \`\`\`jsx live style={{border: '1px solid red'}} - -#### `filename` or `title` + It only specifies syntax like \`\`\`jsx live style={{border: '1px solid red'}}. This RFC chooses `filename` over alternatives such as `title`. `filename` appears to be the closest to a "popular" choice in existing projects today. From 4649f04d353f21bd2dd50d4a6464ba23fd6814e5 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Thu, 14 Nov 2024 09:53:59 -0500 Subject: [PATCH 6/8] nit: or title --- rfcs/configure-file-name-from-block-meta.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfcs/configure-file-name-from-block-meta.md b/rfcs/configure-file-name-from-block-meta.md index c392506e..73ad0256 100644 --- a/rfcs/configure-file-name-from-block-meta.md +++ b/rfcs/configure-file-name-from-block-meta.md @@ -64,7 +64,7 @@ Alternately, if multiple codeblocks require the same _file_ name, developers can ### Parsing Meta There is no unified standard in the ecosystem for parsing codeblock metadata in Markdown. -The syntax has roughly converged on the syntax looking like \`\`\`lang key="value", and to a lesser extent, using `filename` as the prop name. +The syntax has roughly converged on the syntax looking like \`\`\`lang key="value", and to a lesser extent, using `filename` or `title` as the prop name. - [Docusaurus's `codeBlockTitleRegex`](https://github.com/facebook/docusaurus/blob/7650829e913ec4bb1263d855719779f6b97066b6/packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts#L12): only supports a [code title prop](https://mdxjs.com/guides/syntax-highlighting/#syntax-highlighting-with-the-meta-field) like \`\`\`jsx title="/src/components/HelloCodeTitle.js". - [Expressive Code's `title`](https://expressive-code.com/key-features/code-component/#title): used by [Astro](https://astro.build), with the syntax \`\`\`js title="my-test-file.js". From 6d818c9a6b6aa42e4c5f23f704b7752b87aa2305 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Thu, 14 Nov 2024 09:54:23 -0500 Subject: [PATCH 7/8] nit: remove mention of filename being more popular than title --- rfcs/configure-file-name-from-block-meta.md | 1 - 1 file changed, 1 deletion(-) diff --git a/rfcs/configure-file-name-from-block-meta.md b/rfcs/configure-file-name-from-block-meta.md index 73ad0256..4135bdb6 100644 --- a/rfcs/configure-file-name-from-block-meta.md +++ b/rfcs/configure-file-name-from-block-meta.md @@ -78,7 +78,6 @@ The syntax has roughly converged on the syntax looking like \`\`\`lang key It only specifies syntax like \`\`\`jsx live style={{border: '1px solid red'}}. This RFC chooses `filename` over alternatives such as `title`. -`filename` appears to be the closest to a "popular" choice in existing projects today. As noted in [docusaurus/discussions#10033 Choice of filename vs. title for codeblocks](https://github.com/facebook/docusaurus/discussions/10033), `filename` implies a source code file names, whereas `title` implies the visual display. ## Related Discussions From 7da3a1658ce88c89d23f325138c8945c0705e76a Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Thu, 14 Nov 2024 09:54:39 -0500 Subject: [PATCH 8/8] nit: pluralization --- rfcs/configure-file-name-from-block-meta.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfcs/configure-file-name-from-block-meta.md b/rfcs/configure-file-name-from-block-meta.md index 4135bdb6..eba5d7a7 100644 --- a/rfcs/configure-file-name-from-block-meta.md +++ b/rfcs/configure-file-name-from-block-meta.md @@ -78,7 +78,7 @@ The syntax has roughly converged on the syntax looking like \`\`\`lang key It only specifies syntax like \`\`\`jsx live style={{border: '1px solid red'}}. This RFC chooses `filename` over alternatives such as `title`. -As noted in [docusaurus/discussions#10033 Choice of filename vs. title for codeblocks](https://github.com/facebook/docusaurus/discussions/10033), `filename` implies a source code file names, whereas `title` implies the visual display. +As noted in [docusaurus/discussions#10033 Choice of filename vs. title for codeblocks](https://github.com/facebook/docusaurus/discussions/10033), `filename` implies a source code file name, whereas `title` implies the visual display. ## Related Discussions