Skip to content

Commit

Permalink
feat: support parsing markdown via eslint-mdx natively (#621)
Browse files Browse the repository at this point in the history
  • Loading branch information
JounQin committed Dec 24, 2023
1 parent 5f762df commit 2b09e7f
Show file tree
Hide file tree
Showing 11 changed files with 97 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .changeset/slimy-boats-fold.md
@@ -1,5 +1,5 @@
---
'eslint-plugin-prettier': patch
"eslint-plugin-prettier": patch
---

Add exports mapping to package.json, to allow `import eslintPluginRecommended from 'eslint-plugin-prettier/recommended'` to work as expected.
Expand Down
5 changes: 5 additions & 0 deletions .changeset/warm-cougars-attack.md
@@ -0,0 +1,5 @@
---
"eslint-plugin-prettier": patch
---

feat: support parsing `markdown` via `eslint-mdx` natively
10 changes: 9 additions & 1 deletion .prettierrc
@@ -1,5 +1,13 @@
{
"arrowParens": "avoid",
"singleQuote": true,
"plugins": ["@prettier/plugin-pug", "prettier-plugin-pkg"]
"plugins": ["@prettier/plugin-pug", "prettier-plugin-pkg"],
"overrides": [
{
"files": ".changeset/**/*",
"options": {
"singleQuote": false
}
}
]
}
14 changes: 12 additions & 2 deletions eslint-plugin-prettier.js
Expand Up @@ -9,8 +9,10 @@
* @typedef {import('eslint').AST.Range} Range
* @typedef {import('eslint').AST.SourceLocation} SourceLocation
* @typedef {import('eslint').ESLint.Plugin} Plugin
* @typedef {import('eslint').ESLint.ObjectMetaProperties} ObjectMetaProperties
* @typedef {import('prettier').FileInfoOptions} FileInfoOptions
* @typedef {import('prettier').Options & { onDiskFilepath: string, parserPath: string, usePrettierrc?: boolean }} Options
* @typedef {import('prettier').Options} PrettierOptions
* @typedef {PrettierOptions & { onDiskFilepath: string, parserMeta?: ObjectMetaProperties['meta'], parserPath?: string, usePrettierrc?: boolean }} Options
*/

'use strict';
Expand Down Expand Up @@ -167,10 +169,12 @@ const eslintPluginPrettier = {
}

/**
* @type {{}}
* @type {PrettierOptions}
*/
const eslintPrettierOptions = context.options[0] || {};

const parser = context.languageOptions?.parser;

// prettier.format() may throw a SyntaxError if it cannot parse the
// source code it is given. Usually for JS files this isn't a
// problem as ESLint will report invalid syntax before trying to
Expand All @@ -190,6 +194,12 @@ const eslintPluginPrettier = {
...eslintPrettierOptions,
filepath,
onDiskFilepath,
parserMeta:
parser &&
(parser.meta ?? {
name: parser.name,
version: parser.version,
}),
parserPath: context.parserPath,
usePrettierrc,
},
Expand Down
8 changes: 0 additions & 8 deletions eslint.config.js
Expand Up @@ -25,14 +25,6 @@ module.exports = [
'eslint-plugin/report-message-format': ['error', '^[^a-z].*\\.$'],
},
},
{
files: ['**/*.md'],
rules: { 'prettier/prettier': ['error', { parser: 'markdown' }] },
},
{
files: ['**/*.mdx'],
rules: { 'prettier/prettier': ['error', { parser: 'mdx' }] },
},
// Global ignores
// If a config block only contains an `ignores` key, then the globs are
// ignored globally
Expand Down
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -99,7 +99,8 @@
},
"pnpm": {
"patchedDependencies": {
"@graphql-eslint/eslint-plugin@3.20.0": "patches/@graphql-eslint__eslint-plugin@3.20.0.patch"
"@graphql-eslint/eslint-plugin@3.20.0": "patches/@graphql-eslint__eslint-plugin@3.20.0.patch",
"@types/eslint@8.44.7": "patches/@types__eslint@8.44.7.patch"
}
}
}
14 changes: 14 additions & 0 deletions patches/@types__eslint@8.44.7.patch
@@ -0,0 +1,14 @@
diff --git a/index.d.ts b/index.d.ts
index 75ae420e38148c632230763f26382ef0d9024427..6b8b08da2e25b54dedf41f1db0f2ba6e2c718b30 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -753,6 +753,9 @@ export namespace Rule {
id: string;
options: any[];
settings: { [name: string]: any };
+ languageOptions: {
+ parser: Linter.ParserModule;
+ } & Linter.ParserOptions;
parserPath: string;
parserOptions: Linter.ParserOptions;
parserServices: SourceCode.ParserServices;
8 changes: 6 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions test/fixtures/md.md
@@ -0,0 +1,5 @@
# Heading

```ts
export declare const x = 1
```
22 changes: 21 additions & 1 deletion test/prettier.js
Expand Up @@ -38,7 +38,7 @@ const eslint = new ESLint({
extends: 'plugin:prettier/recommended',
overrides: [
{
files: '*.mdx',
files: ['*.{md,mdx}'],
extends: 'plugin:mdx/recommended',
settings: {
'mdx/code-block': true,
Expand Down Expand Up @@ -228,6 +228,26 @@ mdxRuleTester.run('eslint-plugin-mdx', rule, {
],
});

runFixture('*.md', [
[
{
column: 27,
endColumn: 27,
endLine: 4,
fix: {
range: [43, 43],
text: ';',
},
line: 4,
message: 'Insert `;`',
messageId: 'insert',
nodeType: null,
ruleId: 'prettier/prettier',
severity: 2,
},
],
]);

runFixture('*.mdx', [
[
{
Expand Down
27 changes: 22 additions & 5 deletions worker.js
Expand Up @@ -2,7 +2,8 @@

/**
* @typedef {import('prettier').FileInfoOptions} FileInfoOptions
* @typedef {import('prettier').Options & { onDiskFilepath: string, parserPath?: string, usePrettierrc?: boolean }} Options
* @typedef {import('eslint').ESLint.ObjectMetaProperties} ObjectMetaProperties
* @typedef {import('prettier').Options & { onDiskFilepath: string, parserMeta?: ObjectMetaProperties['meta'], parserPath?: string, usePrettierrc?: boolean }} Options
*/

const { runAsWorker } = require('synckit');
Expand All @@ -24,6 +25,7 @@ runAsWorker(
{
filepath,
onDiskFilepath,
parserMeta,
parserPath,
usePrettierrc,
...eslintPrettierOptions
Expand Down Expand Up @@ -58,7 +60,7 @@ runAsWorker(
return;
}

const initialOptions = {};
const initialOptions = { parser: inferredParser ?? 'babel' };

// ESLint supports processors that let you extract and lint JS
// fragments within a non-JS language. In the cases where prettier
Expand Down Expand Up @@ -94,9 +96,9 @@ runAsWorker(
// 2. `eslint-plugin-html`
// 3. `eslint-plugin-markdown@1` (replacement: `eslint-plugin-markdown@2+`)
// 4. `eslint-plugin-svelte3` (replacement: `eslint-plugin-svelte@2+`)
const parserBlocklist = [null, 'markdown', 'html'];
const parserBlocklist = ['html'];

let inferParserToBabel = parserBlocklist.includes(inferredParser);
let inferParserToBabel = parserBlocklist.includes(initialOptions.parser);

switch (inferredParser) {
// it could be processed by `@graphql-eslint/eslint-plugin` or `eslint-plugin-graphql`
Expand All @@ -109,12 +111,24 @@ runAsWorker(
}
break;
}
case 'markdown': {
// it could be processed by `eslint-plugin-markdown@1` or correctly parsed by `eslint-mdx`
if (
(typeof parserMeta !== 'undefined' &&
parserMeta.name !== 'eslint-mdx') ||
(typeof parserPath === 'string' &&
!/([\\/])eslint-mdx\1/.test(parserPath))
) {
inferParserToBabel = true;
}
break;
}
// it could be processed by `@ota-meshi/eslint-plugin-svelte`, `eslint-plugin-svelte` or `eslint-plugin-svelte3`
case 'svelte': {
// The `source` would be modified by `eslint-plugin-svelte3`
if (
typeof parserPath === 'string' &&
!parserPath.includes('svelte-eslint-parser')
!/([\\/])svelte-eslint-parser\1/.test(parserPath)
) {
// We do not support `eslint-plugin-svelte3`,
// the users should run `prettier` on `.svelte` files manually
Expand Down Expand Up @@ -152,6 +166,9 @@ runAsWorker(
}
}

/**
* @type {import('prettier').Options}
*/
const prettierOptions = {
...initialOptions,
...prettierRcOptions,
Expand Down

0 comments on commit 2b09e7f

Please sign in to comment.