Skip to content

Conversation

TKDev7
Copy link
Contributor

@TKDev7 TKDev7 commented Aug 25, 2025

Prerequisites checklist

What is the purpose of this pull request?

This pull request introduces a new rule, fenced-code-meta, that enforces a consistent policy for metadata in fenced code block info strings. It allows teams to require metadata when a language is specified or to disallow metadata entirely.

What changes did you make? (Give an overview)

  • Added a rule that validates the presence or absence of metadata based on the configured mode
  • Added documentation
  • Added tests

Related Issues

Fixes #477

Is there anything you'd like reviewers to focus on?

@eslintbot eslintbot added this to Triage Aug 25, 2025
@github-project-automation github-project-automation bot moved this to Needs Triage in Triage Aug 25, 2025
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This pull request introduces a new ESLint rule fenced-code-meta that enforces consistent policies for metadata in fenced code block info strings. The rule can either require metadata when a language is specified ("always" mode) or disallow metadata entirely ("never" mode).

  • Added a new rule that validates the presence or absence of metadata in fenced code blocks
  • Comprehensive test coverage for both backtick and tilde fenced code blocks with various configurations
  • Complete documentation with examples and usage guidelines

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/rules/fenced-code-meta.js Implements the core rule logic for validating fenced code block metadata
tests/rules/fenced-code-meta.test.js Comprehensive test suite covering valid and invalid cases for both rule modes
docs/rules/fenced-code-meta.md User documentation with examples and configuration options
README.md Updates rule table and formatting improvements for ESLint disable comments

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Copy link
Member

@nzakas nzakas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this. Overall it looks good. I think the Copilot comments bring up good points, so please take a look at those. Also, double-check the CI errors.

@nzakas nzakas moved this from Needs Triage to Implementing in Triage Aug 26, 2025
nzakas
nzakas previously approved these changes Aug 27, 2025
Copy link
Member

@nzakas nzakas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Would like another review before merging.

@nzakas nzakas moved this from Implementing to Second Review Needed in Triage Aug 27, 2025

## Background

Fenced code blocks can include an info string after the opening fence. The first word typically specifies the language (e.g., `js`). Many tools also support additional metadata after the language (separated by whitespace), such as titles or line highlighting parameters. This rule enforces a consistent policy for including such metadata.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Fenced code blocks can include an info string after the opening fence. The first word typically specifies the language (e.g., `js`). Many tools also support additional metadata after the language (separated by whitespace), such as titles or line highlighting parameters. This rule enforces a consistent policy for including such metadata.
Fenced code blocks can include an information string after the opening fence. The first word typically specifies the language (e.g., `js`). Many tools also support additional metadata after the language (separated by whitespace), such as titles or line highlighting parameters. This rule enforces a consistent policy for including such metadata.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'Info string' is the term used in the CommonMark spec, so I stuck with that for consistency. Happy to adjust if you think 'information string' reads better in context.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should stick with "info string":
https://spec.commonmark.org/0.31.2/#info-string

@TKDev7 when referencing the spec, go ahead and include a link to the section you're referring to. That helps move the conversation forward.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do 👍

Comment on lines +37 to +41
schema: [
{
enum: ["always", "never"],
},
],
Copy link
Contributor

@snitin315 snitin315 Aug 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest we define a schema option for more flexibility, like { required: "always" | "never" } or { required: boolean }. This approach would make it easier to extend the options in the future without introducing breaking changes. I’d like to hear the team’s thoughts on this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking we could follow the pattern many ESLint rules use — keep "always" / "never" as the first option, and add an object as a second argument later if needed. That way we avoid a breaking change and keep the config simple for now. Open to switching if the team prefers the object-based config upfront though!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using "always" and "never" makes sense. There are plenty of rules that follow this pattern.


return {
code(node) {
const lineText = sourceCode.lines[node.position.start.line - 1];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using sourceCode.lines directly to calculate loc.end.column when reporting may lead to incorrect location reporting, as shown below:

AST

   ```js
console.log('hi');
```

The invalid test case below now fails: the endColumn would be 9, but it reports 12.

		{
			code: "   ```js\nconsole.log('hi');\n```",
			errors: [
				{
					messageId: "missingMetadata",
					line: 1,
					column: 4,
					endLine: 1,
					endColumn: 9,
				},
			],
		},

}

if (node.meta) {
const metaStart = lineText.lastIndexOf(node.meta);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems the invalid code below also reports incorrect column and endColumn positions.

end: 10 and endColumn: 12 would be correct, but it reports end: 13 and endColumn: 15.

		{
			code: "   ```js hi\nconsole.log('hi');\n```",
			options: ["never"],
			errors: [
				{
					messageId: "disallowedMetadata",
					line: 1,
					column: 10,
					endLine: 1,
					endColumn: 12,
				},
			],
		},

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Second Review Needed
Development

Successfully merging this pull request may close these issues.

Rule Change: Add fenced-code-meta rule
4 participants