eslint-plugin-prettier 3.2.0 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # Changelog
2
2
 
3
+ ## v3.4.1 (2021-08-20)
4
+
5
+ * build(deps): Bump glob-parent from 5.0.0 to 5.1.2 ([#420](git@github.com:prettier/eslint-plugin-prettier/issues/420)) ([b6d075c](git@github.com:prettier/eslint-plugin-prettier/commit/b6d075cf7111468e8af4161c306c7f37f09f220e))
6
+ * build(deps): Bump path-parse from 1.0.6 to 1.0.7 ([#425](git@github.com:prettier/eslint-plugin-prettier/issues/425)) ([24f957e](git@github.com:prettier/eslint-plugin-prettier/commit/24f957ee2a5476bb9cc8e64921b9841fc751391e))
7
+ * feat: support `@graphql-eslint/eslint-plugin` out of box ([#413](git@github.com:prettier/eslint-plugin-prettier/issues/413)) ([ec6fbb1](git@github.com:prettier/eslint-plugin-prettier/commit/ec6fbb159e2454c6e145db55480932dc953cf7c1))
8
+ * chore: add tests for Node 16 ([#410](git@github.com:prettier/eslint-plugin-prettier/issues/410)) ([76bd45e](git@github.com:prettier/eslint-plugin-prettier/commit/76bd45ece6d56eb52f75db6b4a1efdd2efb56392))
9
+
10
+ ## v3.4.0 (2021-04-15)
11
+
12
+ * feat: support processor virtual filename ([#401](git@github.com:prettier/eslint-plugin-prettier/issues/401)) ([ee0ccc6](git@github.com:prettier/eslint-plugin-prettier/commit/ee0ccc6ac06d13cd546e78b444e53164f59eb27f))
13
+ * Simplify report logic ([#380](git@github.com:prettier/eslint-plugin-prettier/issues/380)) ([d993f24](git@github.com:prettier/eslint-plugin-prettier/commit/d993f247b5661683af031ab3b93955a0dfe448fa))
14
+ * Update: README.md ([#375](git@github.com:prettier/eslint-plugin-prettier/issues/375)) ([3ea4242](git@github.com:prettier/eslint-plugin-prettier/commit/3ea4242a8d4acdb76eb7e7dca9e44d3e87db70e3))
15
+
16
+ ## v3.3.1 (2021-01-04)
17
+
18
+ * fix: add eslint-config-prettier as an optional peer dependency ([#374](git@github.com:prettier/eslint-plugin-prettier/issues/374)) ([d59df27](git@github.com:prettier/eslint-plugin-prettier/commit/d59df27890aaffec9e528ceb3155831a0261848d))
19
+ * build(deps-dev): bump eslint from 7.16.0 to 7.17.0 ([b87985d](git@github.com:prettier/eslint-plugin-prettier/commit/b87985d8b1986743374b56691bcc1633df8f4eae))
20
+ * build(deps-dev): bump eslint from 7.15.0 to 7.16.0 ([11e427e](git@github.com:prettier/eslint-plugin-prettier/commit/11e427e5d6cedeb26e3e03c8143be3496a24955a))
21
+
22
+ ## v3.3.0 (2020-12-13)
23
+
24
+ * Minor: Perf improvement: Do not clear the config cache on each run ([#368](git@github.com:prettier/eslint-plugin-prettier/issues/368)) ([1b90ea7](git@github.com:prettier/eslint-plugin-prettier/commit/1b90ea752636959babb27ebca5d67093c346dab9))
25
+ * Add peerDependenciesMeta block ([#367](git@github.com:prettier/eslint-plugin-prettier/issues/367)) ([86608d5](git@github.com:prettier/eslint-plugin-prettier/commit/86608d5084692ab0d1f2f49a3df4909d04c39ae7))
26
+ * build(deps-dev): bump eslint from 7.14.0 to 7.15.0 ([885f484](git@github.com:prettier/eslint-plugin-prettier/commit/885f48405e0fc9f312acdd3e3487c824bd59c102))
27
+ * build(deps-dev): bump eslint from 7.3.1 to 7.14.0 ([cebc80b](git@github.com:prettier/eslint-plugin-prettier/commit/cebc80b39d3d09f957a73536e54f6d8dd4567080))
28
+
3
29
  ## v3.2.0 (2020-12-03)
4
30
 
5
31
  * Skip CI for eslint 6 + node 8 ([#364](git@github.com:prettier/eslint-plugin-prettier/issues/364)) ([f8f08e4](git@github.com:prettier/eslint-plugin-prettier/commit/f8f08e483522d74bc4dd93d9813914aa7ba9314b))
package/README.md CHANGED
@@ -4,6 +4,8 @@ Runs [Prettier](https://github.com/prettier/prettier) as an [ESLint](http://esli
4
4
 
5
5
  If your desired formatting does not match Prettier’s output, you should use a different tool such as [prettier-eslint](https://github.com/prettier/prettier-eslint) instead.
6
6
 
7
+ Please read [Integrating with linters](https://prettier.io/docs/en/integrating-with-linters.html) before installing.
8
+
7
9
  ## Sample
8
10
 
9
11
  ```js
@@ -74,20 +76,6 @@ This plugin ships with a `plugin:prettier/recommended` config that sets up both
74
76
 
75
77
  You can then set Prettier's own options inside a `.prettierrc` file.
76
78
 
77
- 3. Some ESLint plugins (such as [eslint-plugin-react](https://github.com/yannickcr/eslint-plugin-react)) also contain rules that conflict with Prettier. Add extra exclusions for the plugins you use like so:
78
-
79
- ```json
80
- {
81
- "extends": [
82
- "plugin:prettier/recommended",
83
- "prettier/flowtype",
84
- "prettier/react"
85
- ]
86
- }
87
- ```
88
-
89
- For the list of every available exclusion rule set, please see the [readme of eslint-config-prettier](https://github.com/prettier/eslint-config-prettier/blob/master/README.md).
90
-
91
79
  Exactly what does `plugin:prettier/recommended` do? Well, this is what it expands to:
92
80
 
93
81
  ```json
@@ -102,7 +90,7 @@ Exactly what does `plugin:prettier/recommended` do? Well, this is what it expand
102
90
  }
103
91
  ```
104
92
 
105
- - `"extends": ["prettier"]` enables the main config from `eslint-config-prettier`, which turns off some ESLint core rules that conflict with Prettier.
93
+ - `"extends": ["prettier"]` enables the config from `eslint-config-prettier`, which turns off some ESLint rules that conflict with Prettier.
106
94
  - `"plugins": ["prettier"]` registers this plugin.
107
95
  - `"prettier/prettier": "error"` turns on the rule provided by this plugin, which runs Prettier from within ESLint.
108
96
  - `"arrow-body-style": "off"` and `"prefer-arrow-callback": "off"` turns off two ESLint core rules that unfortunately are problematic with this plugin – see the next section.
@@ -9,6 +9,9 @@
9
9
  // Requirements
10
10
  // ------------------------------------------------------------------------------
11
11
 
12
+ const fs = require('fs');
13
+ const path = require('path');
14
+
12
15
  const {
13
16
  showInvisibles,
14
17
  generateDifferences
@@ -25,6 +28,9 @@ const { INSERT, DELETE, REPLACE } = generateDifferences;
25
28
  // ------------------------------------------------------------------------------
26
29
 
27
30
  // Lazily-loaded Prettier.
31
+ /**
32
+ * @type {import('prettier')}
33
+ */
28
34
  let prettier;
29
35
 
30
36
  // ------------------------------------------------------------------------------
@@ -32,72 +38,49 @@ let prettier;
32
38
  // ------------------------------------------------------------------------------
33
39
 
34
40
  /**
35
- * Reports an "Insert ..." issue where text must be inserted.
36
- * @param {RuleContext} context - The ESLint rule context.
37
- * @param {number} offset - The source offset where to insert text.
38
- * @param {string} text - The text to be inserted.
41
+ * Reports a difference.
42
+ * @param {import('eslint').Rule.RuleContext} context - The ESLint rule context.
43
+ * @param {import('prettier-linter-helpers').Difference} difference - The difference object.
39
44
  * @returns {void}
40
45
  */
41
- function reportInsert(context, offset, text) {
42
- const pos = context.getSourceCode().getLocFromIndex(offset);
43
- const range = [offset, offset];
44
- context.report({
45
- message: 'Insert `{{ code }}`',
46
- data: { code: showInvisibles(text) },
47
- loc: { start: pos, end: pos },
48
- fix(fixer) {
49
- return fixer.insertTextAfterRange(range, text);
50
- }
51
- });
52
- }
46
+ function reportDifference(context, difference) {
47
+ const { operation, offset, deleteText = '', insertText = '' } = difference;
48
+ const range = [offset, offset + deleteText.length];
49
+ const [start, end] = range.map(index =>
50
+ context.getSourceCode().getLocFromIndex(index)
51
+ );
53
52
 
54
- /**
55
- * Reports a "Delete ..." issue where text must be deleted.
56
- * @param {RuleContext} context - The ESLint rule context.
57
- * @param {number} offset - The source offset where to delete text.
58
- * @param {string} text - The text to be deleted.
59
- * @returns {void}
60
- */
61
- function reportDelete(context, offset, text) {
62
- const start = context.getSourceCode().getLocFromIndex(offset);
63
- const end = context.getSourceCode().getLocFromIndex(offset + text.length);
64
- const range = [offset, offset + text.length];
65
53
  context.report({
66
- message: 'Delete `{{ code }}`',
67
- data: { code: showInvisibles(text) },
54
+ messageId: operation,
55
+ data: {
56
+ deleteText: showInvisibles(deleteText),
57
+ insertText: showInvisibles(insertText)
58
+ },
68
59
  loc: { start, end },
69
- fix(fixer) {
70
- return fixer.removeRange(range);
71
- }
60
+ fix: fixer => fixer.replaceTextRange(range, insertText)
72
61
  });
73
62
  }
74
63
 
75
64
  /**
76
- * Reports a "Replace ... with ..." issue where text must be replaced.
77
- * @param {RuleContext} context - The ESLint rule context.
78
- * @param {number} offset - The source offset where to replace deleted text
79
- with inserted text.
80
- * @param {string} deleteText - The text to be deleted.
81
- * @param {string} insertText - The text to be inserted.
82
- * @returns {void}
65
+ * Given a filepath, get the nearest path that is a regular file.
66
+ * The filepath provided by eslint may be a virtual filepath rather than a file
67
+ * on disk. This attempts to transform a virtual path into an on-disk path
68
+ * @param {string} filepath
69
+ * @returns {string}
83
70
  */
84
- function reportReplace(context, offset, deleteText, insertText) {
85
- const start = context.getSourceCode().getLocFromIndex(offset);
86
- const end = context
87
- .getSourceCode()
88
- .getLocFromIndex(offset + deleteText.length);
89
- const range = [offset, offset + deleteText.length];
90
- context.report({
91
- message: 'Replace `{{ deleteCode }}` with `{{ insertCode }}`',
92
- data: {
93
- deleteCode: showInvisibles(deleteText),
94
- insertCode: showInvisibles(insertText)
95
- },
96
- loc: { start, end },
97
- fix(fixer) {
98
- return fixer.replaceTextRange(range, insertText);
71
+ function getOnDiskFilepath(filepath) {
72
+ try {
73
+ if (fs.statSync(filepath).isFile()) {
74
+ return filepath;
99
75
  }
100
- });
76
+ } catch (err) {
77
+ // https://github.com/eslint/eslint/issues/11989
78
+ if (err.code === 'ENOTDIR') {
79
+ return getOnDiskFilepath(path.dirname(filepath));
80
+ }
81
+ }
82
+
83
+ return filepath;
101
84
  }
102
85
 
103
86
  // ------------------------------------------------------------------------------
@@ -143,7 +126,12 @@ module.exports = {
143
126
  },
144
127
  additionalProperties: true
145
128
  }
146
- ]
129
+ ],
130
+ messages: {
131
+ [INSERT]: 'Insert `{{ insertText }}`',
132
+ [DELETE]: 'Delete `{{ deleteText }}`',
133
+ [REPLACE]: 'Replace `{{ deleteText }}` with `{{ insertText }}`'
134
+ }
147
135
  },
148
136
  create(context) {
149
137
  const usePrettierrc =
@@ -152,17 +140,16 @@ module.exports = {
152
140
  (context.options[1] && context.options[1].fileInfoOptions) || {};
153
141
  const sourceCode = context.getSourceCode();
154
142
  const filepath = context.getFilename();
143
+ // Processors that extract content from a file, such as the markdown
144
+ // plugin extracting fenced code blocks may choose to specify virtual
145
+ // file paths. If this is the case then we need to resolve prettier
146
+ // config and file info using the on-disk path instead of the virtual
147
+ // path.
148
+ // See https://github.com/eslint/eslint/issues/11989 for ideas around
149
+ // being able to get this value directly from eslint in the future.
150
+ const onDiskFilepath = getOnDiskFilepath(filepath);
155
151
  const source = sourceCode.text;
156
152
 
157
- // This allows long-running ESLint processes (e.g. vscode-eslint) to
158
- // pick up changes to .prettierrc without restarting the editor. This
159
- // will invalidate the prettier plugin cache on every file as well which
160
- // will make ESLint very slow, so it would probably be a good idea to
161
- // find a better way to do this.
162
- if (usePrettierrc && prettier && prettier.clearConfigCache) {
163
- prettier.clearConfigCache();
164
- }
165
-
166
153
  return {
167
154
  Program() {
168
155
  if (!prettier) {
@@ -173,13 +160,13 @@ module.exports = {
173
160
  const eslintPrettierOptions = context.options[0] || {};
174
161
 
175
162
  const prettierRcOptions = usePrettierrc
176
- ? prettier.resolveConfig.sync(filepath, {
163
+ ? prettier.resolveConfig.sync(onDiskFilepath, {
177
164
  editorconfig: true
178
165
  })
179
166
  : null;
180
167
 
181
- const prettierFileInfo = prettier.getFileInfo.sync(
182
- filepath,
168
+ const { ignored, inferredParser } = prettier.getFileInfo.sync(
169
+ onDiskFilepath,
183
170
  Object.assign(
184
171
  {},
185
172
  { resolveConfig: true, ignorePath: '.prettierignore' },
@@ -188,13 +175,13 @@ module.exports = {
188
175
  );
189
176
 
190
177
  // Skip if file is ignored using a .prettierignore file
191
- if (prettierFileInfo.ignored) {
178
+ if (ignored) {
192
179
  return;
193
180
  }
194
181
 
195
182
  const initialOptions = {};
196
183
 
197
- // ESLint suppports processors that let you extract and lint JS
184
+ // ESLint supports processors that let you extract and lint JS
198
185
  // fragments within a non-JS language. In the cases where prettier
199
186
  // supports the same language as a processor, we want to process
200
187
  // the provided source code as javascript (as ESLint provides the
@@ -202,9 +189,14 @@ module.exports = {
202
189
  // based off the filename. Otherwise, for instance, on a .md file we
203
190
  // end up trying to run prettier over a fragment of JS using the
204
191
  // markdown parser, which throws an error.
205
- // If we can't infer the parser from from the filename, either
206
- // because no filename was provided or because there is no parser
207
- // found for the filename, use javascript.
192
+ // Processors may set virtual filenames for these extracted blocks.
193
+ // If they do so then we want to trust the file extension they
194
+ // provide, and no override is needed.
195
+ // If the processor does not set any virtual filename (signified by
196
+ // `filepath` and `onDiskFilepath` being equal) AND we can't
197
+ // infer the parser from the filename, either because no filename
198
+ // was provided or because there is no parser found for the
199
+ // filename, use javascript.
208
200
  // This is added to the options first, so that
209
201
  // prettierRcOptions and eslintPrettierOptions can still override
210
202
  // the parser.
@@ -214,10 +206,21 @@ module.exports = {
214
206
  // * Prettier supports parsing the file type
215
207
  // * There is an ESLint processor that extracts JavaScript snippets
216
208
  // from the file type.
217
- const parserBlocklist = [null, 'graphql', 'markdown', 'html'];
209
+ const parserBlocklist = [null, 'markdown', 'html'];
210
+
211
+ let inferParserToBabel =
212
+ parserBlocklist.indexOf(inferredParser) !== -1;
213
+
218
214
  if (
219
- parserBlocklist.indexOf(prettierFileInfo.inferredParser) !== -1
215
+ // it could be processed by `@graphql-eslint/eslint-plugin` or `eslint-plugin-graphql`
216
+ inferredParser === 'graphql' &&
217
+ // for `eslint-plugin-graphql`, see https://github.com/apollographql/eslint-plugin-graphql/blob/master/src/index.js#L416
218
+ source.startsWith('ESLintPluginGraphQLFile`')
220
219
  ) {
220
+ inferParserToBabel = true;
221
+ }
222
+
223
+ if (filepath === onDiskFilepath && inferParserToBabel) {
221
224
  // Prettier v1.16.0 renamed the `babylon` parser to `babel`
222
225
  // Use the modern name if available
223
226
  const supportBabelParser = prettier
@@ -236,7 +239,7 @@ module.exports = {
236
239
  );
237
240
 
238
241
  // prettier.format() may throw a SyntaxError if it cannot parse the
239
- // source code it is given. Ususally for JS files this isn't a
242
+ // source code it is given. Usually for JS files this isn't a
240
243
  // problem as ESLint will report invalid syntax before trying to
241
244
  // pass it to the prettier plugin. However this might be a problem
242
245
  // for non-JS languages that are handled by a plugin. Notably Vue
@@ -254,7 +257,7 @@ module.exports = {
254
257
  let message = 'Parsing error: ' + err.message;
255
258
 
256
259
  // Prettier's message contains a codeframe style preview of the
257
- // invalid code and the line/column at which the error occured.
260
+ // invalid code and the line/column at which the error occurred.
258
261
  // ESLint shows those pieces of information elsewhere already so
259
262
  // remove them from the message
260
263
  if (err.codeFrame) {
@@ -272,32 +275,9 @@ module.exports = {
272
275
  if (source !== prettierSource) {
273
276
  const differences = generateDifferences(source, prettierSource);
274
277
 
275
- differences.forEach(difference => {
276
- switch (difference.operation) {
277
- case INSERT:
278
- reportInsert(
279
- context,
280
- difference.offset,
281
- difference.insertText
282
- );
283
- break;
284
- case DELETE:
285
- reportDelete(
286
- context,
287
- difference.offset,
288
- difference.deleteText
289
- );
290
- break;
291
- case REPLACE:
292
- reportReplace(
293
- context,
294
- difference.offset,
295
- difference.deleteText,
296
- difference.insertText
297
- );
298
- break;
299
- }
300
- });
278
+ for (const difference of differences) {
279
+ reportDifference(context, difference);
280
+ }
301
281
  }
302
282
  }
303
283
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-prettier",
3
- "version": "3.2.0",
3
+ "version": "3.4.1",
4
4
  "description": "Runs prettier as an eslint rule",
5
5
  "keywords": [
6
6
  "eslint",
@@ -46,6 +46,11 @@
46
46
  "prettier": "^1.15.3",
47
47
  "vue-eslint-parser": "^6.0.0"
48
48
  },
49
+ "peerDependenciesMeta": {
50
+ "eslint-config-prettier": {
51
+ "optional": true
52
+ }
53
+ },
49
54
  "engines": {
50
55
  "node": ">=6.0.0"
51
56
  },