|
| 1 | +# RFC: Configuring File Name from Block Meta |
| 2 | + |
| 3 | +## Summary |
| 4 | + |
| 5 | +Allowing codeblocks to change the `filename` used in `eslint-plugin-markdown`'s processor using codeblock `meta` text. |
| 6 | + |
| 7 | +## Motivation |
| 8 | + |
| 9 | +Some projects use ESLint `overrides` to run different lint rules on files based on their file name. |
| 10 | +There's no way to respect file name based `overrides` in parsed Markdown codeblocks right now using `eslint-plugin-markdown`'s parsing. |
| 11 | +This RFC would allow codeblocks to specify a custom file name so that `overrides` can be used more idiomatically. |
| 12 | + |
| 13 | +### Real-World Example |
| 14 | + |
| 15 | +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). |
| 16 | +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`. |
| 17 | +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. |
| 18 | + |
| 19 | +## Detailed Design |
| 20 | + |
| 21 | +This RFC proposes that codeblocks be allowed to specify a file path in `meta` (the \`\`\` opening fence) with `filename="..."`. |
| 22 | +Doing so would replace the `filename` provided by `eslint-plugin-markdown`'s `preprocess` method. |
| 23 | + |
| 24 | +````md |
| 25 | +```json filename="package.json" |
| 26 | +{} |
| 27 | +``` |
| 28 | +```` |
| 29 | + |
| 30 | +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). |
| 31 | + |
| 32 | +Parsed language is ignored when the codeblock provides a custom title. |
| 33 | +Some languages have many file extensions, such as TypeScript's `.cts`, `.ts`, `.tsx`, etc. |
| 34 | +Some extensions may map to multiple languages, such as Perl and Prolog both using `.pl`. |
| 35 | + |
| 36 | +Roughly: |
| 37 | + |
| 38 | +```diff |
| 39 | +- filename: `${index}.${block.lang.trim().split(" ")[0]}`, |
| 40 | ++ filename: titleFromMeta(block) ?? `${index}.${block.lang.trim().split(" ")[0]}`, |
| 41 | +``` |
| 42 | + |
| 43 | +### Name Uniqueness |
| 44 | + |
| 45 | +Codeblocks must have unique file paths for ESLint processing. |
| 46 | +[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 <code>\`${i}_${block.filename}\`</code>. |
| 47 | +For example, given three codeblocks with the same name, the names in order would become: |
| 48 | + |
| 49 | +- `example`: `0_example`, `1_example`, `2_example` |
| 50 | +- `example.js`: `0_example.js`, `1_example.js`, `2_example.js` |
| 51 | + |
| 52 | +Alternately, if multiple codeblocks require the same _file_ name, developers can give different _directory paths_: |
| 53 | + |
| 54 | +````md |
| 55 | +```json filename="example-1/package.json" |
| 56 | +{} |
| 57 | +``` |
| 58 | + |
| 59 | +```json filename="example-2/package.json" |
| 60 | +{} |
| 61 | +``` |
| 62 | +```` |
| 63 | + |
| 64 | +### Parsing Meta |
| 65 | + |
| 66 | +There is no unified standard in the ecosystem for parsing codeblock metadata in Markdown. |
| 67 | +The syntax has roughly converged on the syntax looking like <code>\`\`\`lang key="value"</code>, and to a lesser extent, using `filename` or `title` as the prop name. |
| 68 | + |
| 69 | +- [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 <code>\`\`\`jsx title="/src/components/HelloCodeTitle.js"</code>. |
| 70 | +- [Expressive Code's `title`](https://expressive-code.com/key-features/code-component/#title): used by [Astro](https://astro.build), with the syntax <code>\`\`\`js title="my-test-file.js"</code>. |
| 71 | +- Gatsby plugins such as [`gatsby-remark-prismjs`](https://www.gatsbyjs.com/plugins/gatsby-remark-prismjs) rely on a syntax like <code>\`\`\`javascript{numberLines: true}`</code>. |
| 72 | + - Separately, [`gatsby-remark-code-titles`](https://www.gatsbyjs.com/plugins/gatsby-remark-code-titles) allows a syntax like <code>\`\`\`js:title=example-file.js</code>. |
| 73 | +- [`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 | + It specifies syntax like <code>\`\`\`js copy filename="awesome.js"</code>, with a suggestion of `filename` for just the file's name. |
| 75 | + - [`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. |
| 76 | + It also specified syntax like <code>\`\`\`js copy filename="awesome.js" onUsage={props.beAwesome} {...props}</code>. |
| 77 | +- [`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). |
| 78 | + It only specifies syntax like <code>\`\`\`jsx live style={{border: '1px solid red'}}</code>. |
| 79 | + |
| 80 | +This RFC chooses `filename` over alternatives such as `title`. |
| 81 | +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. |
| 82 | + |
| 83 | +## Related Discussions |
| 84 | + |
| 85 | +See #226 for the original issue. |
| 86 | +This RFC is intended to contain a superset of all information discussed there. |
0 commit comments