-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
docs: [RFC] Configuring File Name from Block Meta #230
Open
JoshuaKGoldberg
wants to merge
8
commits into
eslint:main
Choose a base branch
from
JoshuaKGoldberg:rfc-file-name-from-block-meta
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+86
−0
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
31a8106
RFC: Configuring File Name from Block Meta
JoshuaKGoldberg 7da2410
Sequential names, and filename over title
JoshuaKGoldberg 86b721c
Update the examples too
JoshuaKGoldberg a9de58f
PR feedback, and 'code( )block' normalization
JoshuaKGoldberg ac14f2a
Also mention Expressive Code
JoshuaKGoldberg 4649f04
nit: or title
JoshuaKGoldberg 6d818c9
nit: remove mention of filename being more popular than title
JoshuaKGoldberg 7da3a16
nit: pluralization
JoshuaKGoldberg File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# RFC: Configuring File Name from Block Meta | ||
|
||
## Summary | ||
|
||
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 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 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 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 | ||
```json filename="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). | ||
|
||
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. | ||
[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>. | ||
For example, given three codeblocks with the same name, the names in order would become: | ||
|
||
- `example`: `0_example`, `1_example`, `2_example` | ||
- `example.js`: `0_example.js`, `1_example.js`, `2_example.js` | ||
|
||
Alternately, if multiple codeblocks require the same _file_ name, developers can give different _directory paths_: | ||
|
||
````md | ||
```json filename="example-1/package.json" | ||
{} | ||
``` | ||
|
||
```json filename="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 <code>\`\`\`lang key="value"</code>, 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 <code>\`\`\`jsx title="/src/components/HelloCodeTitle.js"</code>. | ||
- [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>. | ||
- 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>. | ||
- 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>. | ||
- [`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 <code>\`\`\`js copy filename="awesome.js"</code>, 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 <code>\`\`\`js copy filename="awesome.js" onUsage={props.beAwesome} {...props}</code>. | ||
- [`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 <code>\`\`\`jsx live style={{border: '1px solid red'}}</code>. | ||
|
||
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 name, whereas `title` implies the visual display. | ||
|
||
## Related Discussions | ||
|
||
See #226 for the original issue. | ||
This RFC is intended to contain a superset of all information discussed there. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a few edge cases that will need to be considered. For example, what will happen when a path includes invalid or reserved characters, or when the name of an existing file is used (e.g.
filename: "../../package.json"
), or how to indicate paths that include both'
and"
, etc. But I think it is fine to discuss those details in the implementation PR.