Giter VIP home page Giter VIP logo

eslint-plugin-md's Introduction

eslint-plugin-md

An ESLint plugin to lint and fix markdown files. It uses amazing remark-lint under the hood. Also enables using prettier to automatically format your markdown files right from eslint!

Motivation

ESLint is a tool for linting Javascript. There is another plugin called eslint-plugin-markdown, however it is still only linting Javascript parts inside *.md files, and leaves Markdown itself untouched.

Wouldn't it be cool, if we could use ESLint to enforce style of Markdown itself? That is what this plugin is for!

Installation

You'll first need to install ESLint:

$ npm i eslint --save-dev
# or
$ yarn add -D eslint

Next, install eslint-plugin-md:

$ npm install eslint-plugin-md --save-dev
# or
$ yarn add -D eslint-plugin-md

Note: If you installed ESLint globally (using the npm -g or yarn global) then you must also install eslint-plugin-md globally.

Usage

Add plugin:md/recommended config to extends section of your your .eslintrc configuration file

// .eslintrc.js
module.exports = {
  extends: ['plugin:md/recommended'],
  overrides: [
    {
      files: ['*.md'],
      parser: 'markdown-eslint-parser',
    },
  ],
}

And this is it! By default it will apply all rules from Markdown style guide.

Note: By default ESLint won't lint *.md files. So:

  • If you use ESLint from CLI, use --ext parameter (e.g. eslint . --ext js,md)
  • If you use VSCode with ESLint plugin, add "eslint.validate": ["markdown"] in your VSCode preferences

Usage with eslint-plugin-prettier

Prettier is an amazing code formatter that supports many languages, including markdown. It is common to use prettier as a rule in ESLint via amazing eslint-plugin-prettier.

This plugin can play nicely together with eslint-plugin-prettier (meaning that first code will be formatted via prettier, and then remark rules will be applied). Typical eslint configuration will look like this:

yarn add -D eslint eslint-plugin-prettier eslint-plugin-md
// .eslintrc.js
module.exports = {
  extends: ['plugin:prettier/recommended', 'plugin:md/recommended'],
  overrides: [
    {
      files: ['*.md'],
      parser: 'markdown-eslint-parser',
      rules: {
        'prettier/prettier': [
          'error',
          // Important to force prettier to use "markdown" parser - otherwise it wouldn't be able to parse *.md files.
          // You also can configure other options supported by prettier here - "prose-wrap" is
          // particularly useful for *.md files
          { parser: 'markdown' },
        ],
      },
    },
  ],
}

Modifying eslint setup for js code inside *.md files

By default, code inside fenced code block marked as js language (```js) will be linted against your default eslint configuration for js files. However, that may be undesirable - usually you will want less strict rules for JS code in *.md files.

To modify setup, you can use "overrides" section in your eslintrc in this way:

// .eslintrc.js
module.exports = {
  extends: ['plugin:md/recommended'],
  overrides: [
    {
      files: ['*.md'],
      parser: 'markdown-eslint-parser',
    },
    {
      files: ['*.md.js'], // Will match js code inside *.md files
      rules: {
        // Example - disable 2 core eslint rules 'no-unused-vars' and 'no-undef'
        'no-unused-vars': 'off',
        'no-undef': 'off',
      },
    },
  ],
}

Supported Rules

This plugin exposes only one eslint rule - md/remark. However, you can customize remark configuration however you wish.

// .eslintrc.js
module.exports = {
  extends: ['plugin:md/recommended'],
  rules: {
    'md/remark': [
      'error',
      {
        // This object corresponds to object you would export in .remarkrc file
        plugins: ['preset-lint-markdown-style-guide', 'frontmatter', ['lint-maximum-line-length', false]],
      },
    ],
  },
  overrides: [
    {
      files: ['*.md'],
      parser: 'markdown-eslint-parser',
    },
  ],
}

"Plugin" in remark can mean many things, but for our purposes it can be either remark rule or remark preset. See list of available rules here, and list of available presets (=set of rules) here.

Remark also supports External rules. You can use those as well, just make sure to install corresponding package first. For example, if you want to use alphabetize-lists external rule:

yarn add -D remark-lint-alphabetize-lists
// .eslintrc.js
module.exports = {
  extends: ['plugin:md/recommended'],
  rules: {
    'md/remark': [
      'error',
      {
        // This object corresponds to object you would export in .remarkrc file
        plugins: ['preset-lint-markdown-style-guide', 'frontmatter', 'remark-lint-alphabetize-lists'],
      },
    ],
  },
  overrides: [
    {
      files: ['*.md'],
      parser: 'markdown-eslint-parser',
    },
  ],
}

eslint-plugin-md's People

Contributors

leo-buneev avatar llwsh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

eslint-plugin-md's Issues

`lint-no-missing-blank-lines` doesn't play nice with this plugin

I was trying to use the lint-no-missing-blank-lines rule with this package, but ran into some problems. Given a Markdown file with the following content:

# Example

foobar

```js
let x = 42;
console.log(x);
```

Using this plugin with ESLint

module.exports = {
  overrides: [
    {
      files: ["**/*.md"],
      parser: "markdown-eslint-parser",
      extends: [
        "plugin:md/recommended",
      ],
      rules: {
        "md/remark": ["error",{
          plugins: [
            ["lint-no-missing-blank-lines"],
          ]
      },
    },
  ],
};

Gives the following errors:

  6:1  error  Missing blank line before block node (no-missing-blank-lines)  md/remark
  7:1  error  Missing blank line before block node (no-missing-blank-lines)  md/remark
  8:1  error  Missing blank line before block node (no-missing-blank-lines)  md/remark

Whereas a similar setup using remark-lint directly reports no errors, see https://codesandbox.io/s/remark-debug-forked-w8w1w?file=/src/index.js

I'm guessing this plugin/ESLint is doing something to the file that confuses remark, but I wasn't able to figure out what...

Disabling rules

I'm strugging with disabling rules using the .eslintrc.js file. All of the output is tagged as "md/remark", so if I disable that rule everything get's disabled.
14:59 error Missing new line after list item (list-item-spacing) md/remark

How can I disable the "list-item-spacing" rule?

Thanks!

[Feature request] Ignore files

It would be nice to have a way to fully ignore files that I don't want get linted/fixed (for example, a LICENSE file).

Maybe a <!-- eslint-disable --> at the top?

[Bug] Doesn't parse indented code blocks

When the codeblock is indented followed by a codeblock that is not, the parser has a really bad time trying to parse it.

I created a repo with a reproduction case: https://github.com/scinos/eslint-md-parsing-error

Input:

- list

  ```js
  foo()
  ```

---

```js
bar()
```

Lint errors (./node_modules/.bin/eslint .):

   3:3  error  Insert `··`                              prettier/prettier
   4:1  error  Insert `··`                              prettier/prettier
   5:1  error  Insert `··`                              prettier/prettier
   6:1  error  Insert `··`                              prettier/prettier
   7:1  error  Insert `··`                              prettier/prettier
   8:1  error  Insert `··`                              prettier/prettier
   9:1  error  Insert `··`                              prettier/prettier
  10:1  error  Insert `··`                              prettier/prettier
  11:1  error  Insert `··`                              prettier/prettier
   5:3  error  Parsing error: Unexpected character '`'

Output when using autofix (./node_modules/.bin/eslint . --fix):

          -   list

    ```js
    foo()
  ```

---
  
```js
bar()
```

I found two workarounds:

  1. Removing the language tag from the first codeblock
  2. Un-indenting the first codeblock

Abandoned?

is this project still maintained? dependabot has been ignored for a few years now and there are a few high risk vulnerabilities in the old versions that this project depends on.

"Cannot read property 'tokens' of undefined" error

Version of the eslint-plugin-md: 1.0.19

I have an error when trying to parse a markdown file wiht code snippets and when the code is fenced. I'm getting this error:

Cannot read property 'tokens' of undefined
TypeError: Cannot read property 'tokens' of undefined
    at validate (/home/[...]/node_modules/eslint/lib/util/source-code.js:28:14)
    at ...

Example of files and configuration causing the error:

README.md

npm start --dry-run

.eslintrc (yaml syntax):

extends:
    - "plugin:md/recommended"

rules:
    md/remark: 
        - error
        - plugins: 
            - "preset-lint-markdown-style-guide"
            - 
                - "lint-fenced-code-flag"
                - allowEmpty: true
            -
                - "lint-ordered-list-marker-value"
                - "ordered"

overrides:
    -
        files:
            - "*.md"
        parser: "markdown-eslint-parser"

I've seen that in the mdProcessor.js of this plugin, line 34, inside preprocess function, it is storing some sort of filename with the extension of the code snippet appended to it and perhaps it could be giving problems:

const jsBlocksResult = nonMdBlocksInner.map(({ text, lang }, i) => ({
      text,
      // eslint internal code appends this filename to real filename
      filename: `/../../${partName}.${lang}`,
    }))

As you can see in the example, I disabled the lint-fenced-code-flag in order to be able to pass the validation by removing the language from the code snippets, but this is not an option since I have many md files plenty of this feature.

Disabled log JSBR and MG by default.

my english is not good, sorry.
thanks for your works, eslint-plugin-md is amazing for me.
but there is only one trouble prevent i use it in my project.
it is the extra logging about JSBR and MG.
looking forward to your reply 👍

Formatting with Prettier not working

Hi, I am loving this library already. Linting entire Markdown files with ESLint is great, so I'm glad you put this together.

I am having trouble getting this to work as expected with Prettier though. It is not formatting my files to account for line-length.

Here is my .prettierrc.json:

{
	"semi": true,
	"singleQuote": true,
	"tabWidth": 2,
	"useTabs": false,
	"trailingComma": "all",
	"printWidth": 80,
	"overrides": [
		{
			"files": "*.json",
			"options": {
				"trailingComma": "none"
			}
		},
		{
			"files": [
				"*.md"
			],
			"options": {
				"parser": "markdown",
				"rules": {
					"prettier/prettier": [
						"error",
						{
							"parser": "markdown"
						}
					]
				}
			}
		}
	]
}

and here is my .eslintrc.json:

{
	"semi": true,
	"singleQuote": true,
	"tabWidth": 2,
	"useTabs": false,
	"trailingComma": "all",
	"printWidth": 80,
	"overrides": [
		{
			"files": "*.json",
			"options": {
				"trailingComma": "none"
			}
		},
		{
			"files": [
				"*.md"
			],
			"options": {
				"parser": "markdown",
				"rules": {
					"prettier/prettier": [
						"error",
						{
							"parser": "markdown"
						}
					]
				}
			}
		}
	]
}

and here are the dependencies from my package.json:

"dependencies": {
    "fibers": "^4.0.2",
    "glob": "^7.1.6",
    "gray-matter": "^4.0.2",
    "isomorphic-unfetch": "^3.0.0",
    "next": "^9.3.1",
    "node-sass": "^4.13.1",
    "raw-loader": "^4.0.0",
    "react": "^16.13.1",
    "react-addons-shallow-compare": "^15.6.2",
    "react-dom": "^16.13.1",
    "react-markdown": "^4.3.1",
    "react-syntax-highlighter": "^12.2.1",
    "sass": "^1.26.3",
    "styled-components": "^5.1.0",
    "swr": "^0.1.18"
  },
  "devDependencies": {
    "babel-plugin-styled-components": "^1.10.7",
    "eslint": "^7.2.0",
    "eslint-config-prettier": "^6.11.0",
    "eslint-plugin-json": "^2.1.1",
    "eslint-plugin-md": "^1.0.15",
    "eslint-plugin-prettier": "^3.1.3",
    "eslint-plugin-react": "^7.20.0",
    "eslint-plugin-react-hooks": "^4.0.4",
    "husky": "^4.2.5",
    "lint-staged": ">=10",
    "markdown-eslint-parser": "^1.2.1",
    "prettier": "2.0.5"
  },

For reference, I am using VSCode, but I can't get this working from the CLI either. I would appreciate any help you can provide!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.