Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/max-len.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"eslint-plugin-markdown-preferences": minor
---

feat: add `markdown-preferences/max-len` rule
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,26 @@ The rules with the following 💄 are included in the `standard` config.

<!--RULES_TABLE_START-->

### Layout & Formatting Rules

<!-- eslint-disable markdown-links/no-dead-urls -- Auto generated -->

<!-- prettier-ignore-start -->

| Rule ID | Description | Fixable | Config |
| :---------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------- | :-----: | :----: |
| [markdown-preferences/max-len](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/max-len.html) | enforce maximum length for various Markdown entities | | 💄 |

<!-- prettier-ignore-end -->

<!-- eslint-enable markdown-links/no-dead-urls -- Auto generated -->

### Preference Rules

- Rules to unify the expression and description style of documents.

<!-- eslint-disable markdown-links/no-dead-urls -- Auto generated -->

<!-- prettier-ignore-start -->

| Rule ID | Description | Fixable | Config |
Expand All @@ -157,10 +173,14 @@ The rules with the following 💄 are included in the `standard` config.

<!-- prettier-ignore-end -->

<!-- eslint-enable markdown-links/no-dead-urls -- Auto generated -->

### Notation Rules

- Rules related to notation styles in Markdown.

<!-- eslint-disable markdown-links/no-dead-urls -- Auto generated -->

<!-- prettier-ignore-start -->

| Rule ID | Description | Fixable | Config |
Expand All @@ -185,10 +205,14 @@ The rules with the following 💄 are included in the `standard` config.

<!-- prettier-ignore-end -->

<!-- eslint-enable markdown-links/no-dead-urls -- Auto generated -->

### Whitespace Rules

- Rules related to whitespace styles in Markdown.

<!-- eslint-disable markdown-links/no-dead-urls -- Auto generated -->

<!-- prettier-ignore-start -->

| Rule ID | Description | Fixable | Config |
Expand All @@ -212,10 +236,14 @@ The rules with the following 💄 are included in the `standard` config.

<!-- prettier-ignore-end -->

<!-- eslint-enable markdown-links/no-dead-urls -- Auto generated -->

### Decorative Rules

- Rules related to visual or stylistic decorations in Markdown.

<!-- eslint-disable markdown-links/no-dead-urls -- Auto generated -->

<!-- prettier-ignore-start -->

| Rule ID | Description | Fixable | Config |
Expand All @@ -234,6 +262,8 @@ The rules with the following 💄 are included in the `standard` config.

<!-- prettier-ignore-end -->

<!-- eslint-enable markdown-links/no-dead-urls -- Auto generated -->

<!--RULES_TABLE_END-->

<!--RULES_SECTION_END-->
Expand Down
10 changes: 10 additions & 0 deletions docs/rules/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ The rules with the following 💄 are included in the `plugin.configs.standard`

<!-- This file is automatically generated in tools/update-docs-rules-index.js, do not change! -->

## Layout & Formatting Rules

<!-- prettier-ignore-start -->

| Rule ID | Description | Fixable | Config |
| :------------------------------------------- | :--------------------------------------------------- | :-----: | :----: |
| [markdown-preferences/max-len](./max-len.md) | enforce maximum length for various Markdown entities | | 💄 |

<!-- prettier-ignore-end -->

## Preference Rules

- Rules to unify the expression and description style of documents.
Expand Down
124 changes: 124 additions & 0 deletions docs/rules/max-len.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
---
pageClass: "rule-details"
sidebarDepth: 0
title: "markdown-preferences/max-len"
description: "enforce maximum length for various Markdown entities"
---

# markdown-preferences/max-len

> enforce maximum length for various Markdown entities

- ❗ <badge text="This rule has not been released yet." vertical="middle" type="error"> **_This rule has not been released yet._** </badge>
- ⚙️ This rule is included in `plugin.configs.standard`.

## 📖 Rule Details

This rule enforces a configurable maximum length for different Markdown entities such as headings, paragraphs, list items, blockquotes, table rows, and optionally code blocks.

Overly long Markdown elements reduce readability, make diffs harder to review, and complicate maintenance. By enforcing reasonable maximum lengths for various entities, documentation remains cleaner, easier to navigate, and more consistent across the project.

<!-- prettier-ignore-start -->

<!-- eslint-skip -->

```md
<!-- eslint markdown-preferences/max-len: ['error', { heading: 80, paragraph: 120 }] -->

<!-- ✓ GOOD -->

## This heading is within the limit

This is a paragraph that fits comfortably within the specified maximum length limit.

- A list item that is short enough

<!-- ✗ BAD -->

## This is a very long heading that exceeds the default eighty character maximum length

This is an extremely long paragraph that goes on and on and on well beyond the one hundred and twenty character maximum length limit and should be broken up.

- This is a very long list item that definitely exceeds the default one hundred and twenty character maximum length limit and should be reported
```

<!-- prettier-ignore-end -->

## 🔧 Options

This rule accepts an object with the following properties:

```json
{
"markdown-preferences/max-len": [
"error",
{
"heading": 80,
"paragraph": 120,
"listItem": 120,
"blockquote": 120,
"tableRow": 120,
"codeBlock": null,
"ignoreUrls": true
}
]
}
```

### Entity-Specific Options

- `heading` (default: `80`): Maximum line length for headings
- `paragraph` (default: `120`): Maximum line length for paragraphs
- `listItem` (default: `120`): Maximum line length for list items
- `blockquote` (default: `120`): Maximum line length for blockquotes
- `tableRow` (default: `120`): Maximum line length for table rows
- `codeBlock` (default: `null`): Maximum line length for code blocks. Set to `null` to ignore code blocks (recommended)

### URL Handling

- `ignoreUrls` (default: `true`): When enabled, lines containing URLs are ignored if:
- The URL is longer than the maximum line length, or
- The line would be within the limit without the URL

This option works similarly to [`@stylistic/eslint-plugin`'s `max-len` rule](https://eslint.style/rules/max-len#ignoreurls).

### Notes on Code Blocks

**Note:** Code blocks are ignored by default (`codeBlock: null`) because:

1. Code inside code blocks should be linted using language-specific linters via ESLint's language plugins
2. The `@eslint/markdown` plugin supports linting code blocks as their respective languages
3. This rule cannot understand the syntax inside code blocks (e.g., comments, strings)

If you need to enforce line length for code blocks in Markdown, you can:
- Use the language-specific ESLint configuration for code blocks (recommended):
```js
{
files: ["**/*.md/*.js"],
rules: {
"@stylistic/max-len": ["error", { "ignoreComments": true }]
}
}
```
- Set the `codeBlock` option to enforce a simple line length limit (not syntax-aware)

For more information, see the [advanced configuration guide](https://github.com/eslint/markdown/blob/main/docs/processors/markdown.md#advanced-configuration).

## 📚 Further Reading

- [Markdownlint MD013](https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md013) - Similar rule in markdownlint
- [@stylistic/eslint-plugin max-len](https://eslint.style/rules/max-len) - ESLint stylistic rule for code

## 👫 Related Rules

- [no-multiple-empty-lines](./no-multiple-empty-lines.md) - Disallow multiple empty lines

## 🔍 Implementation

<!-- eslint-disable markdown-links/no-dead-urls -- Auto generated -->

- [Rule source](https://github.com/ota-meshi/eslint-plugin-markdown-preferences/blob/main/src/rules/max-len.ts)
- [Test source](https://github.com/ota-meshi/eslint-plugin-markdown-preferences/blob/main/tests/src/rules/max-len.ts)
- [Test fixture sources](https://github.com/ota-meshi/eslint-plugin-markdown-preferences/tree/main/tests/fixtures/rules/max-len)

<!-- eslint-enable markdown-links/no-dead-urls -- Auto generated -->
1 change: 1 addition & 0 deletions src/configs/standard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export const rules: Linter.RulesRecord = {
"markdown-preferences/link-paren-spacing": "error",
"markdown-preferences/link-title-style": "error",
"markdown-preferences/list-marker-alignment": "error",
"markdown-preferences/max-len": "error",
"markdown-preferences/no-implicit-block-closing": "error",
"markdown-preferences/no-laziness-blockquotes": "error",
"markdown-preferences/no-multi-spaces": "error",
Expand Down
15 changes: 15 additions & 0 deletions src/rule-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ export interface RuleOptions {
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/list-marker-alignment.html
*/
'markdown-preferences/list-marker-alignment'?: Linter.RuleEntry<MarkdownPreferencesListMarkerAlignment>
/**
* enforce maximum length for various Markdown entities
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/max-len.html
*/
'markdown-preferences/max-len'?: Linter.RuleEntry<MarkdownPreferencesMaxLen>
/**
* disallow trailing punctuation in headings.
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-heading-trailing-punctuation.html
Expand Down Expand Up @@ -433,6 +438,16 @@ type MarkdownPreferencesLinkTitleStyle = []|[{
type MarkdownPreferencesListMarkerAlignment = []|[{
align?: ("left" | "right")
}]
// ----- markdown-preferences/max-len -----
type MarkdownPreferencesMaxLen = []|[{
heading?: number
paragraph?: number
listItem?: number
blockquote?: number
tableRow?: number
codeBlock?: (number | null)
ignoreUrls?: boolean
}]
// ----- markdown-preferences/no-heading-trailing-punctuation -----
type MarkdownPreferencesNoHeadingTrailingPunctuation = []|[{
punctuation?: (string | {
Expand Down
Loading