Skip to content

Commit 2b09e7f

Browse files
authoredDec 24, 2023
feat: support parsing markdown via eslint-mdx natively (#621)
1 parent 5f762df commit 2b09e7f

11 files changed

+97
-21
lines changed
 

‎.changeset/slimy-boats-fold.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
'eslint-plugin-prettier': patch
2+
"eslint-plugin-prettier": patch
33
---
44

55
Add exports mapping to package.json, to allow `import eslintPluginRecommended from 'eslint-plugin-prettier/recommended'` to work as expected.

‎.changeset/warm-cougars-attack.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"eslint-plugin-prettier": patch
3+
---
4+
5+
feat: support parsing `markdown` via `eslint-mdx` natively

‎.prettierrc

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
{
22
"arrowParens": "avoid",
33
"singleQuote": true,
4-
"plugins": ["@prettier/plugin-pug", "prettier-plugin-pkg"]
4+
"plugins": ["@prettier/plugin-pug", "prettier-plugin-pkg"],
5+
"overrides": [
6+
{
7+
"files": ".changeset/**/*",
8+
"options": {
9+
"singleQuote": false
10+
}
11+
}
12+
]
513
}

‎eslint-plugin-prettier.js

+12-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
* @typedef {import('eslint').AST.Range} Range
1010
* @typedef {import('eslint').AST.SourceLocation} SourceLocation
1111
* @typedef {import('eslint').ESLint.Plugin} Plugin
12+
* @typedef {import('eslint').ESLint.ObjectMetaProperties} ObjectMetaProperties
1213
* @typedef {import('prettier').FileInfoOptions} FileInfoOptions
13-
* @typedef {import('prettier').Options & { onDiskFilepath: string, parserPath: string, usePrettierrc?: boolean }} Options
14+
* @typedef {import('prettier').Options} PrettierOptions
15+
* @typedef {PrettierOptions & { onDiskFilepath: string, parserMeta?: ObjectMetaProperties['meta'], parserPath?: string, usePrettierrc?: boolean }} Options
1416
*/
1517

1618
'use strict';
@@ -167,10 +169,12 @@ const eslintPluginPrettier = {
167169
}
168170

169171
/**
170-
* @type {{}}
172+
* @type {PrettierOptions}
171173
*/
172174
const eslintPrettierOptions = context.options[0] || {};
173175

176+
const parser = context.languageOptions?.parser;
177+
174178
// prettier.format() may throw a SyntaxError if it cannot parse the
175179
// source code it is given. Usually for JS files this isn't a
176180
// problem as ESLint will report invalid syntax before trying to
@@ -190,6 +194,12 @@ const eslintPluginPrettier = {
190194
...eslintPrettierOptions,
191195
filepath,
192196
onDiskFilepath,
197+
parserMeta:
198+
parser &&
199+
(parser.meta ?? {
200+
name: parser.name,
201+
version: parser.version,
202+
}),
193203
parserPath: context.parserPath,
194204
usePrettierrc,
195205
},

‎eslint.config.js

-8
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,6 @@ module.exports = [
2525
'eslint-plugin/report-message-format': ['error', '^[^a-z].*\\.$'],
2626
},
2727
},
28-
{
29-
files: ['**/*.md'],
30-
rules: { 'prettier/prettier': ['error', { parser: 'markdown' }] },
31-
},
32-
{
33-
files: ['**/*.mdx'],
34-
rules: { 'prettier/prettier': ['error', { parser: 'mdx' }] },
35-
},
3628
// Global ignores
3729
// If a config block only contains an `ignores` key, then the globs are
3830
// ignored globally

‎package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@
9999
},
100100
"pnpm": {
101101
"patchedDependencies": {
102-
"@graphql-eslint/eslint-plugin@3.20.0": "patches/@graphql-eslint__eslint-plugin@3.20.0.patch"
102+
"@graphql-eslint/eslint-plugin@3.20.0": "patches/@graphql-eslint__eslint-plugin@3.20.0.patch",
103+
"@types/eslint@8.44.7": "patches/@types__eslint@8.44.7.patch"
103104
}
104105
}
105106
}

‎patches/@types__eslint@8.44.7.patch

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
diff --git a/index.d.ts b/index.d.ts
2+
index 75ae420e38148c632230763f26382ef0d9024427..6b8b08da2e25b54dedf41f1db0f2ba6e2c718b30 100644
3+
--- a/index.d.ts
4+
+++ b/index.d.ts
5+
@@ -753,6 +753,9 @@ export namespace Rule {
6+
id: string;
7+
options: any[];
8+
settings: { [name: string]: any };
9+
+ languageOptions: {
10+
+ parser: Linter.ParserModule;
11+
+ } & Linter.ParserOptions;
12+
parserPath: string;
13+
parserOptions: Linter.ParserOptions;
14+
parserServices: SourceCode.ParserServices;

‎pnpm-lock.yaml

+6-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎test/fixtures/md.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Heading
2+
3+
```ts
4+
export declare const x = 1
5+
```

‎test/prettier.js

+21-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const eslint = new ESLint({
3838
extends: 'plugin:prettier/recommended',
3939
overrides: [
4040
{
41-
files: '*.mdx',
41+
files: ['*.{md,mdx}'],
4242
extends: 'plugin:mdx/recommended',
4343
settings: {
4444
'mdx/code-block': true,
@@ -228,6 +228,26 @@ mdxRuleTester.run('eslint-plugin-mdx', rule, {
228228
],
229229
});
230230

231+
runFixture('*.md', [
232+
[
233+
{
234+
column: 27,
235+
endColumn: 27,
236+
endLine: 4,
237+
fix: {
238+
range: [43, 43],
239+
text: ';',
240+
},
241+
line: 4,
242+
message: 'Insert `;`',
243+
messageId: 'insert',
244+
nodeType: null,
245+
ruleId: 'prettier/prettier',
246+
severity: 2,
247+
},
248+
],
249+
]);
250+
231251
runFixture('*.mdx', [
232252
[
233253
{

‎worker.js

+22-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
/**
44
* @typedef {import('prettier').FileInfoOptions} FileInfoOptions
5-
* @typedef {import('prettier').Options & { onDiskFilepath: string, parserPath?: string, usePrettierrc?: boolean }} Options
5+
* @typedef {import('eslint').ESLint.ObjectMetaProperties} ObjectMetaProperties
6+
* @typedef {import('prettier').Options & { onDiskFilepath: string, parserMeta?: ObjectMetaProperties['meta'], parserPath?: string, usePrettierrc?: boolean }} Options
67
*/
78

89
const { runAsWorker } = require('synckit');
@@ -24,6 +25,7 @@ runAsWorker(
2425
{
2526
filepath,
2627
onDiskFilepath,
28+
parserMeta,
2729
parserPath,
2830
usePrettierrc,
2931
...eslintPrettierOptions
@@ -58,7 +60,7 @@ runAsWorker(
5860
return;
5961
}
6062

61-
const initialOptions = {};
63+
const initialOptions = { parser: inferredParser ?? 'babel' };
6264

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

99-
let inferParserToBabel = parserBlocklist.includes(inferredParser);
101+
let inferParserToBabel = parserBlocklist.includes(initialOptions.parser);
100102

101103
switch (inferredParser) {
102104
// it could be processed by `@graphql-eslint/eslint-plugin` or `eslint-plugin-graphql`
@@ -109,12 +111,24 @@ runAsWorker(
109111
}
110112
break;
111113
}
114+
case 'markdown': {
115+
// it could be processed by `eslint-plugin-markdown@1` or correctly parsed by `eslint-mdx`
116+
if (
117+
(typeof parserMeta !== 'undefined' &&
118+
parserMeta.name !== 'eslint-mdx') ||
119+
(typeof parserPath === 'string' &&
120+
!/([\\/])eslint-mdx\1/.test(parserPath))
121+
) {
122+
inferParserToBabel = true;
123+
}
124+
break;
125+
}
112126
// it could be processed by `@ota-meshi/eslint-plugin-svelte`, `eslint-plugin-svelte` or `eslint-plugin-svelte3`
113127
case 'svelte': {
114128
// The `source` would be modified by `eslint-plugin-svelte3`
115129
if (
116130
typeof parserPath === 'string' &&
117-
!parserPath.includes('svelte-eslint-parser')
131+
!/([\\/])svelte-eslint-parser\1/.test(parserPath)
118132
) {
119133
// We do not support `eslint-plugin-svelte3`,
120134
// the users should run `prettier` on `.svelte` files manually
@@ -152,6 +166,9 @@ runAsWorker(
152166
}
153167
}
154168

169+
/**
170+
* @type {import('prettier').Options}
171+
*/
155172
const prettierOptions = {
156173
...initialOptions,
157174
...prettierRcOptions,

0 commit comments

Comments
 (0)
Please sign in to comment.