Skip to content

Commit

Permalink
feat: skip processing code blocks on specific languages like `styleli…
Browse files Browse the repository at this point in the history
…nt-prettier` (#415)
  • Loading branch information
JounQin committed Jun 27, 2022
1 parent 42bfe88 commit 52eec48
Show file tree
Hide file tree
Showing 8 changed files with 1,495 additions and 997 deletions.
1 change: 1 addition & 0 deletions .eslintignore
@@ -1 +1,2 @@
!.eslintrc.js
test/fixtures
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Expand Up @@ -15,10 +15,10 @@ jobs:
node-version: [12, 14, 16]

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}

Expand Down
61 changes: 46 additions & 15 deletions eslint-plugin-prettier.js
Expand Up @@ -179,22 +179,53 @@ module.exports = {
// * Prettier supports parsing the file type
// * There is an ESLint processor that extracts JavaScript snippets
// from the file type.
const parserBlocklist = [null, 'markdown', 'html'];

let inferParserToBabel =
parserBlocklist.indexOf(inferredParser) !== -1;

if (
// it could be processed by `@graphql-eslint/eslint-plugin` or `eslint-plugin-graphql`
inferredParser === 'graphql' &&
// for `eslint-plugin-graphql`, see https://github.com/apollographql/eslint-plugin-graphql/blob/master/src/index.js#L416
source.startsWith('ESLintPluginGraphQLFile`')
) {
inferParserToBabel = true;
}
if (filepath === onDiskFilepath) {
// The following list means the plugin process source into js content
// but with same filename, so we need to change the parser to `babel`
// by default.
// Related ESLint plugins are:
// 1. `eslint-plugin-graphql` (replacement: `@graphql-eslint/eslint-plugin`)
// 2. `eslint-plugin-markdown@1` (replacement: `eslint-plugin-markdown@2+`)
// 3. `eslint-plugin-html`
const parserBlocklist = [null, 'markdown', 'html'];

let inferParserToBabel =
parserBlocklist.indexOf(inferredParser) !== -1;

if (
// it could be processed by `@graphql-eslint/eslint-plugin` or `eslint-plugin-graphql`
inferredParser === 'graphql' &&
// for `eslint-plugin-graphql`, see https://github.com/apollographql/eslint-plugin-graphql/blob/master/src/index.js#L416
source.startsWith('ESLintPluginGraphQLFile`')
) {
inferParserToBabel = true;
}

if (filepath === onDiskFilepath && inferParserToBabel) {
initialOptions.parser = 'babel';
if (inferParserToBabel) {
initialOptions.parser = 'babel';
}
} else {
// Similar to https://github.com/prettier/stylelint-prettier/pull/22
// In all of the following cases ESLint extracts a part of a file to
// be formatted and there exists a prettier parser for the whole file.
// If you're interested in prettier you'll want a fully formatted file so
// you're about to run prettier over the whole file anyway.
// Therefore running prettier over just the style section is wasteful, so
// skip it.
const parserBlocklist = [
'babel',
'babylon',
'flow',
'typescript',
'vue',
'markdown',
'html',
'mdx',
'angular',
];
if (parserBlocklist.indexOf(inferredParser) !== -1) {
return;
}
}

const prettierOptions = Object.assign(
Expand Down
25 changes: 16 additions & 9 deletions package.json
Expand Up @@ -35,26 +35,33 @@
"prettier": ">=2.0.0"
},
"devDependencies": {
"@graphql-eslint/eslint-plugin": "^2.3.0",
"@graphql-eslint/eslint-plugin": "^2.5.0",
"@not-an-aardvark/node-release-script": "^0.1.0",
"eslint": "^8.1.0",
"@typescript-eslint/parser": "^5.29.0",
"eslint": "^8.18.0",
"eslint-config-not-an-aardvark": "^2.1.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-eslint-plugin": "^4.0.2",
"eslint-config-prettier": "^8.5.0",
"eslint-mdx": "^1.17.0",
"eslint-plugin-eslint-plugin": "^4.3.0",
"eslint-plugin-mdx": "^1.17.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "link:.",
"eslint-plugin-self": "^1.2.1",
"graphql": "^15.7.1",
"mocha": "^6.2.3",
"prettier": "^2.4.1",
"vue-eslint-parser": "^8.0.0"
"graphql": "^16.5.0",
"mocha": "^9.2.2",
"prettier": "^2.7.1",
"vue-eslint-parser": "^8.3.0"
},
"peerDependenciesMeta": {
"eslint-config-prettier": {
"optional": true
}
},
"resolutions": {
"@babel/traverse": "^7.18.5"
},
"engines": {
"node": ">=6.0.0"
"node": ">=12.0.0"
},
"license": "MIT"
}
7 changes: 7 additions & 0 deletions test/fixtures/mdx.mdx
@@ -0,0 +1,7 @@
import { Fragment } from 'react'

<div>Hello World!</div>

```ts
export declare const x = 1
```
20 changes: 20 additions & 0 deletions test/invalid/mdx.txt
@@ -0,0 +1,20 @@
CODE:
import React from 'react'

<div>Hello World</div>

OUTPUT:
import React from 'react';

<div>Hello World</div>

OPTIONS:
[]

ERRORS:
[
{
message: 'Insert `;`',
line: 1, column: 26, endLine: 1, endColumn: 26,
},
]
108 changes: 107 additions & 1 deletion test/prettier.js
Expand Up @@ -18,12 +18,38 @@ const path = require('path');
const eslintPluginPrettier = require('..');

const rule = eslintPluginPrettier.rules.prettier;
const RuleTester = require('eslint').RuleTester;

const assert = require('assert');
const { ESLint, RuleTester } = require('eslint');

// ------------------------------------------------------------------------------
// Tests
// ------------------------------------------------------------------------------

const eslint = new ESLint({
baseConfig: {
parserOptions: {
ecmaVersion: 2021,
ecmaFeatures: {
jsx: true,
},
sourceType: 'module',
},
extends: 'plugin:prettier/recommended',
overrides: [
{
files: '*.mdx',
extends: 'plugin:mdx/recommended',
settings: {
'mdx/code-block': true,
},
},
],
},
useEslintrc: false,
ignore: false,
});

const ruleTester = new RuleTester();

ruleTester.run('prettier', rule, {
Expand Down Expand Up @@ -154,6 +180,69 @@ eslintPluginGraphqlRuleTester.run('eslint-plugin-graphql', rule, {
invalid: [],
});

const mdxRuleTester = new RuleTester({
parser: require.resolve('eslint-mdx'),
parserOptions: {
...require('eslint-mdx').DEFAULT_PARSER_OPTIONS,
// mdx-js/eslint-mdx#366
ecmaVersion: 2021,
},
});

mdxRuleTester.run('eslint-plugin-mdx', rule, {
valid: [
{
code: [
"import React from 'react';",
'',
'<div>Hello World</div>',
'',
].join('\n'),
filename: 'valid.mdx',
},
],
invalid: [
Object.assign(loadInvalidFixture('mdx'), {
filename: 'invalid.mdx',
}),
],
});

runFixture('mdx', [
[
{
column: 33,
endColumn: 33,
endLine: 1,
fix: {
range: [32, 32],
text: ';',
},
line: 1,
message: 'Insert `;`',
messageId: 'insert',
nodeType: null,
ruleId: 'prettier/prettier',
severity: 2,
},
{
column: 27,
endColumn: 27,
endLine: 6,
fix: {
range: [91, 91],
text: ';',
},
line: 6,
message: 'Insert `;`',
messageId: 'insert',
nodeType: null,
ruleId: 'prettier/prettier',
severity: 2,
},
],
]);

// ------------------------------------------------------------------------------
// Helpers
// ------------------------------------------------------------------------------
Expand Down Expand Up @@ -193,3 +282,20 @@ function loadInvalidFixture(name) {
function getPrettierRcJsFilename(dir, file = 'dummy.js') {
return path.resolve(__dirname, `./prettierrc/${dir}/${file}`);
}

function runFixture(name, asserts) {
return eslint
.lintFiles(`test/fixtures/${name}.*`)
.then((results) =>
assert.deepStrictEqual(
asserts,
results.map(({ messages }) => messages)
)
)
.catch((err) => {
// eslint-disable-next-line no-console
console.error(err);
// eslint-disable-next-line no-process-exit
process.exit(1);
});
}

0 comments on commit 52eec48

Please sign in to comment.