Awesome
ESLint Markdown Language Plugin
Lint JS, JSX, TypeScript, and more inside Markdown.
<img src="screenshot.png" height="142" width="432" alt="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:
npm install --save-dev eslint @eslint/markdown
Configurations
Configuration Name | Description |
---|---|
recommended | Lints all .md files with the recommended rules and assumes CommonMark 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 the Markdown processor on all .md
files:
// eslint.config.js
import markdown from "@eslint/markdown";
export default [
...markdown.configs.recommended
// your other configs here
];
Rules
<!-- NOTE: The following table is autogenerated. Do not manually edit. --> <!-- Rule Table Start -->Rule Name | Description | Recommended |
---|---|---|
fenced-code-language | Require languages for fenced code blocks | yes |
heading-increment | Enforce heading levels increment by one | yes |
no-duplicate-headings | Disallow duplicate headings in the same document | no |
no-empty-links | Disallow empty links | yes |
no-html | Disallow HTML tags | no |
no-invalid-label-refs | Disallow invalid label references | yes |
no-missing-label-refs | Disallow missing label references | yes |
Note: This plugin does not provide formatting rules. We recommend using a source code formatter such as Prettier 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:
// eslint.config.js
import markdown from "@eslint/markdown";
export default [
{
files: ["**/*.md"],
plugins: {
markdown
},
language: "markdown/commonmark",
rules: {
"markdown/no-html": "error"
}
}
];
You can individually disable rules in Markdown using HTML comments, such as:
<!-- eslint-disable-next-line markdown/no-html -- I want to allow HTML here -->
<custom-element>Hello world!</custom-element>
<!-- eslint-disable markdown/no-html -- here too -->
<another-element>Goodbye world!</another-element>
<!-- eslint-enable markdown/no-html -- safe to re-enable now -->
[Object] <!-- eslint-disable-line markdown/no-missing-label-refs -- not meant to be a link ref -->
Languages
Language Name | Description |
---|---|
commonmark | Parse using CommonMark Markdown format |
gfm | Parse using GitHub-Flavored Markdown format |
In order to individually configure a language in your eslint.config.js
file, import @eslint/markdown
and configure a language
:
// eslint.config.js
import markdown from "@eslint/markdown";
export default [
{
files: ["**/*.md"],
plugins: {
markdown
},
language: "markdown/gfm",
rules: {
"markdown/no-html": "error"
}
}
];
Processors
Processor Name | Description |
---|---|
markdown | Extract fenced code blocks from the Markdown code so they can be linted separately. |
Editor Integrations
VSCode
vscode-eslint
has built-in support for the Markdown processor.
Atom
The linter-eslint
package allows for linting within the Atom IDE.
In order to see @eslint/markdown
work its magic within Markdown code blocks in your Atom editor, you can go to linter-eslint
's settings and within "List of scopes to run ESLint on...", add the cursor scope "source.gfm".
However, this reports a problem when viewing Markdown which does not have configuration, so you may wish to use the cursor scope "source.embedded.js", but note that @eslint/markdown
configuration comments and skip directives won't work in this context.
Contributing
$ git clone https://github.com/eslint/markdown.git
$ cd markdown
$ npm install
$ npm test
This project follows the ESLint contribution guidelines.
<!-- NOTE: This section is autogenerated. Do not manually edit.--> <!--sponsorsstart-->Sponsors
The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. Become a Sponsor to get your logo on our READMEs and website.
<h3>Platinum Sponsors</h3> <p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="128"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="128"></a></p><h3>Gold Sponsors</h3> <p><a href="https://trunk.io/"><img src="https://images.opencollective.com/trunkio/fb92d60/avatar.png" alt="trunk.io" height="96"></a></p><h3>Silver Sponsors</h3> <p><a href="https://www.serptriumph.com/"><img src="https://images.opencollective.com/serp-triumph5/fea3074/logo.png" alt="SERP Triumph" height="64"></a> <a href="https://www.jetbrains.com/"><img src="https://images.opencollective.com/jetbrains/fe76f99/logo.png" alt="JetBrains" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301?v=4" alt="American Express" height="64"></a> <a href="https://www.workleap.com"><img src="https://avatars.githubusercontent.com/u/53535748?u=d1e55d7661d724bf2281c1bfd33cb8f99fe2465f&v=4" alt="Workleap" height="64"></a></p><h3>Bronze Sponsors</h3> <p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://syntax.fm"><img src="https://github.com/syntaxfm.png" alt="Syntax" height="32"></a> <a href="https://www.wordhint.net/"><img src="https://images.opencollective.com/wordhint/be86813/avatar.png" alt="WordHint" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340?v=4" alt="GitBook" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104?v=4" alt="Nx" height="32"></a> <a href="https://opensource.mercedes-benz.com/"><img src="https://avatars.githubusercontent.com/u/34240465?v=4" alt="Mercedes-Benz Group" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774?v=4" alt="HeroCoders" height="32"></a></p> <h3>Technology Sponsors</h3> 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. <p><a href="https://netlify.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/netlify-icon.svg" alt="Netlify" height="32"></a> <a href="https://algolia.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/algolia-icon.svg" alt="Algolia" height="32"></a> <a href="https://1password.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/1password-icon.svg" alt="1Password" height="32"></a></p> <!--sponsorsend-->