# ESLint Markdown Language Plugin [![npm Version](https://img.shields.io/npm/v/@eslint/markdown.svg)](https://www.npmjs.com/package/@eslint/markdown) [![Downloads](https://img.shields.io/npm/dm/@eslint/markdown.svg)](https://www.npmjs.com/package/@eslint/markdown) [![Build Status](https://github.com/eslint/markdown/workflows/CI/badge.svg)](https://github.com/eslint/markdown/actions) Lint Markdown with ESLint, as well JS, JSX, TypeScript, and more inside Markdown. A JS code snippet in a Markdown editor has red squiggly underlines. A tooltip explains the problem. ## Usage ### Installing Install the plugin alongside ESLint v9 or greater. For Node.js and compatible runtimes: ```sh npm install @eslint/markdown -D # or yarn add @eslint/markdown -D # or pnpm install @eslint/markdown -D # or bun add @eslint/markdown -D ``` For Deno: ```sh deno add jsr:@eslint/markdown ``` ### Configurations | **Configuration Name** | **Description** | |---------------|-----------------| | `recommended` | Lints all `.md` files with the recommended rules and assumes [CommonMark](https://commonmark.org/) format. | | `processor` | Enables extracting code blocks from all `.md` files so code blocks can be individually linted. | In your `eslint.config.js` file, import `@eslint/markdown` and include the recommended config to enable Markdown parsing and linting: ```js // eslint.config.js import { defineConfig } from "eslint/config"; import markdown from "@eslint/markdown"; export default defineConfig([ markdown.configs.recommended // your other configs here ]); ``` You can also modify the recommended config by using `extends`: ```js // eslint.config.js import { defineConfig } from "eslint/config"; import markdown from "@eslint/markdown"; export default defineConfig([ { plugins: { markdown }, extends: ["markdown/recommended"], rules: { "markdown/no-html": "error" } } // your other configs here ]); ``` ### Rules | **Rule Name** | **Description** | **Recommended** | | :- | :- | :-: | | [`fenced-code-language`](./docs/rules/fenced-code-language.md) | Require languages for fenced code blocks | yes | | [`heading-increment`](./docs/rules/heading-increment.md) | Enforce heading levels increment by one | yes | | [`no-bare-urls`](./docs/rules/no-bare-urls.md) | Disallow bare URLs | no | | [`no-duplicate-definitions`](./docs/rules/no-duplicate-definitions.md) | Disallow duplicate definitions | yes | | [`no-duplicate-headings`](./docs/rules/no-duplicate-headings.md) | Disallow duplicate headings in the same document | no | | [`no-empty-definitions`](./docs/rules/no-empty-definitions.md) | Disallow empty definitions | yes | | [`no-empty-images`](./docs/rules/no-empty-images.md) | Disallow empty images | yes | | [`no-empty-links`](./docs/rules/no-empty-links.md) | Disallow empty links | yes | | [`no-html`](./docs/rules/no-html.md) | Disallow HTML tags | no | | [`no-invalid-label-refs`](./docs/rules/no-invalid-label-refs.md) | Disallow invalid label references | yes | | [`no-missing-atx-heading-space`](./docs/rules/no-missing-atx-heading-space.md) | Disallow headings without a space after the hash characters | yes | | [`no-missing-label-refs`](./docs/rules/no-missing-label-refs.md) | Disallow missing label references | yes | | [`no-missing-link-fragments`](./docs/rules/no-missing-link-fragments.md) | Disallow link fragments that do not reference valid headings | yes | | [`no-multiple-h1`](./docs/rules/no-multiple-h1.md) | Disallow multiple H1 headings in the same document | yes | | [`no-reversed-media-syntax`](./docs/rules/no-reversed-media-syntax.md) | Disallow reversed link and image syntax | yes | | [`no-unused-definitions`](./docs/rules/no-unused-definitions.md) | Disallow unused definitions | yes | | [`require-alt-text`](./docs/rules/require-alt-text.md) | Require alternative text for images | yes | | [`table-column-count`](./docs/rules/table-column-count.md) | Disallow data rows in a GitHub Flavored Markdown table from having more cells than the header row | yes | **Note:** This plugin does not provide formatting rules. We recommend using a source code formatter such as [Prettier](https://prettier.io) for that purpose. In order to individually configure a rule in your `eslint.config.js` file, import `@eslint/markdown` and configure each rule with a prefix: ```js // eslint.config.js import { defineConfig } from "eslint/config"; import markdown from "@eslint/markdown"; export default defineConfig([ { files: ["**/*.md"], plugins: { markdown }, language: "markdown/commonmark", rules: { "markdown/no-html": "error" } } ]); ``` You can individually disable rules in Markdown using HTML comments, such as: ```markdown Hello world! Goodbye world! [Object] ``` ### Languages | **Language Name** | **Description** | |---------------|-----------------| | `commonmark` | Parse using [CommonMark](https://commonmark.org) Markdown format | | `gfm` | Parse using [GitHub-Flavored Markdown](https://github.github.com/gfm/) format | In order to individually configure a language in your `eslint.config.js` file, import `@eslint/markdown` and configure a `language`: ```js // eslint.config.js import { defineConfig } from "eslint/config"; import markdown from "@eslint/markdown"; export default defineConfig([ { files: ["**/*.md"], plugins: { markdown }, language: "markdown/gfm", rules: { "markdown/no-html": "error" } } ]); ``` ### Language Options #### Enabling Front Matter in both `commonmark` and `gfm` By default, Markdown parsers do not support [front matter](https://jekyllrb.com/docs/front-matter/). To enable front matter in both `commonmark` and `gfm`, you can use the `frontmatter` option in `languageOptions`. > `@eslint/markdown` internally uses [`micromark-extension-frontmatter`](https://github.com/micromark/micromark-extension-frontmatter) and [`mdast-util-frontmatter`](https://github.com/syntax-tree/mdast-util-frontmatter) to parse front matter. | **Option Value** | **Description** | |------------------|------------------------------------------------------------| | `false` | Disables front matter parsing in Markdown files. (Default) | | `"yaml"` | Enables YAML front matter parsing in Markdown files. | | `"toml"` | Enables TOML front matter parsing in Markdown files. | | `"json"` | Enables JSON front matter parsing in Markdown files. | ```js // eslint.config.js import { defineConfig } from "eslint/config"; import markdown from "@eslint/markdown"; export default defineConfig([ { files: ["**/*.md"], plugins: { markdown }, language: "markdown/gfm", languageOptions: { frontmatter: "yaml", // Or pass `"toml"` or `"json"` to enable TOML or JSON front matter parsing. }, rules: { "markdown/no-html": "error" } } ]); ``` ### Processors | **Processor Name** | **Description** | |---------------|-----------------| | [`markdown`](./docs/processors/markdown.md) | Extract fenced code blocks from the Markdown code so they can be linted separately. | ## Editor Integrations ### VSCode [`vscode-eslint`](https://github.com/microsoft/vscode-eslint) has built-in support for the Markdown processor. ## File Name Details This processor will use file names from blocks if a `filename` meta is present. For example, the following block will result in a parsed file name of `src/index.js`: ````md ```js filename="src/index.js" export const value = "Hello, world!"; ``` ```` This can be useful for user configurations that include linting overrides for specific file paths. In this example, you could then target the specific code block in your configuration using `"file-name.md/*src/index.js"`. ## Contributing ```sh $ git clone https://github.com/eslint/markdown.git $ cd markdown $ npm install $ npm test ``` This project follows the [ESLint contribution guidelines](https://eslint.org/docs/latest/contribute/). ## Sponsors The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. [Become a Sponsor](https://eslint.org/donate) to get your logo on our READMEs and [website](https://eslint.org/sponsors).

Platinum Sponsors

Automattic Airbnb

Gold Sponsors

Qlty Software trunk.io Shopify

Silver Sponsors

Vite Liftoff American Express StackBlitz

Bronze Sponsors

Cybozu Sentry Anagram Solver Icons8 Discord GitBook Nx Mercedes-Benz Group HeroCoders LambdaTest

Technology Sponsors

Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.

Netlify Algolia 1Password