Skip to content

Commit 2262e7f

Browse files
JounQinphun-ky
andauthored
feat: migrate to TypeScript with 100% compatibility (#1179)
Co-authored-by: Alexander Vassbotn <[email protected]>
1 parent a624d09 commit 2262e7f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+5905
-1380
lines changed

.all-contributorsrc

+4-1
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,10 @@
346346
"name": "Jonathan Rehm",
347347
"avatar_url": "https://avatars.githubusercontent.com/u/999845?v=4",
348348
"profile": "https://jonathan.rehm.me/",
349-
"contributions": ["bug", "code"]
349+
"contributions": [
350+
"bug",
351+
"code"
352+
]
350353
},
351354
{
352355
"login": "gwhitney",

.changeset/pink-dogs-clap.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"prettier-eslint": minor
3+
---
4+
5+
feat: migrate to TypeScript with 100% compatibility

.eslintignore

-5
This file was deleted.

.eslintrc.js

-30
This file was deleted.

.github/workflows/ci.yml

+14-14
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,21 @@ jobs:
2121
fail-fast: false
2222

2323
steps:
24-
- uses: actions/checkout@v4
24+
- uses: actions/checkout@v4
2525

26-
- name: Use Node.js ${{ matrix.node }}
27-
uses: actions/setup-node@v4
28-
with:
29-
node-version: ${{ matrix.node }}
30-
cache: yarn
26+
- name: Use Node.js ${{ matrix.node }}
27+
uses: actions/setup-node@v4
28+
with:
29+
node-version: ${{ matrix.node }}
30+
cache: yarn
3131

32-
- name: Install dependencies
33-
run: yarn --immutable
32+
- name: Install dependencies
33+
run: yarn --immutable
3434

35-
- name: Lint, test, and build
36-
run: yarn start validate
35+
- name: Lint, test, and build
36+
run: yarn start validate
3737

38-
- name: Check test coverage
39-
uses: codecov/codecov-action@v5
40-
with:
41-
token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos
38+
- name: Check test coverage
39+
uses: codecov/codecov-action@v5
40+
with:
41+
token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ dist
88
.yarn/*
99
!.yarn/releases
1010
!.yarn/plugins
11+
!test/fixtures/paths/node_modules

.prettierignore

-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1 @@
11
.yarn
2-
node_modules
3-
.nyc_output
4-
coverage
5-
dist
6-
tests/fixtures/

.prettierrc.json

-5
This file was deleted.

.prettierrc.mjs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// @ts-check
2+
3+
/** @import { Config, Plugin } from 'prettier' */
4+
5+
import base from '@1stg/prettier-config/semi';
6+
import * as jsdoc from 'prettier-plugin-jsdoc';
7+
import * as jsdocType from 'prettier-plugin-jsdoc-type';
8+
import * as svelte from 'prettier-plugin-svelte';
9+
10+
/** @type {Config} */
11+
const config = {
12+
...base,
13+
plugins: [
14+
.../** @type {Plugin[]} */ (base.plugins),
15+
jsdoc,
16+
jsdocType,
17+
svelte,
18+
],
19+
};
20+
21+
export default config;

.yarnrc.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ nodeLinker: node-modules
55
plugins:
66
- checksum: 37b2361b1502b2054e6779788c0e9bdd6a90ce49852a8cad2feda79b0614ec94f06fb6e78951f5f95429c610d7934dd077caa47413a0227378a102c55161616d
77
path: .yarn/plugins/plugin-prepare-lifecycle.cjs
8-
spec: "https://github.com/un-es/yarn-plugin-prepare-lifecycle/releases/download/v0.0.1/index.js"
8+
spec: 'https://github.com/un-es/yarn-plugin-prepare-lifecycle/releases/download/v0.0.1/index.js'
99

1010
yarnPath: .yarn/releases/yarn-4.9.1.cjs
File renamed without changes.

other/EXAMPLES.md renamed to EXAMPLES.md

+9-8
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,21 @@ gulp.task('js:format', function () {
2323

2424
```js
2525
var through = require('through2');
26+
var PluginError = require('plugin-error');
2627
var prettierEslint = require('prettier-eslint');
2728

2829
const options = {
2930
eslintConfig: {
3031
parserOptions: {
31-
ecmaVersion: 7
32+
ecmaVersion: 7,
3233
},
3334
rules: {
34-
semi: ['error', 'never']
35-
}
35+
semi: ['error', 'never'],
36+
},
3637
},
3738
prettierOptions: {
38-
bracketSpacing: true
39-
}
39+
bracketSpacing: true,
40+
},
4041
};
4142

4243
module.exports = function () {
@@ -49,14 +50,14 @@ module.exports = function () {
4950

5051
if (file.isStream()) {
5152
return callback(
52-
new utils.PluginError('prettier-eslint', "doesn't support Streams")
53+
new PluginError('prettier-eslint', "doesn't support Streams"),
5354
);
5455
}
5556

5657
const sourceCode = file.contents.toString();
5758
const formatted = prettierEslint({
58-
...config,
59-
text: sourceCode
59+
...options,
60+
text: sourceCode,
6061
});
6162

6263
file.contents = new Buffer(formatted, encoding);

README.md

+13-13
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ npm install --save-dev prettier-eslint
4848

4949
### Example
5050

51-
```javascript
51+
```js
5252
const format = require('prettier-eslint');
5353

5454
// notice, no semicolon in the original text
@@ -58,18 +58,18 @@ const options = {
5858
text: sourceCode,
5959
eslintConfig: {
6060
parserOptions: {
61-
ecmaVersion: 7
61+
ecmaVersion: 7,
6262
},
6363
rules: {
64-
semi: ['error', 'never']
65-
}
64+
semi: ['error', 'never'],
65+
},
6666
},
6767
prettierOptions: {
68-
bracketSpacing: true
68+
bracketSpacing: true,
6969
},
7070
fallbackPrettierOptions: {
71-
singleQuote: false
72-
}
71+
singleQuote: false,
72+
},
7373
};
7474

7575
const formatted = await format(options);
@@ -150,15 +150,15 @@ This allows you to use `eslint` to look for bugs and/or bad practices, and use
150150

151151
## Capturing ESLint messages
152152

153-
```javascript
153+
```js
154154
const { analyze } = require('prettier-eslint');
155155

156156
const text = 'var x = 0;';
157157
const result = await analyze({
158158
text,
159159
eslintConfig: {
160-
rules: { 'no-var': 'error' }
161-
}
160+
rules: { 'no-var': 'error' },
161+
},
162162
});
163163
console.log(result.messages);
164164
```
@@ -210,7 +210,7 @@ the inference is done for each option (what rule(s) are referenced, etc.) and
210210
ESLint disabled entirely via `/* eslint-disable */` then prettier options will
211211
fall back to the `prettier` defaults:
212212

213-
```javascript
213+
```js
214214
{
215215
printWidth: 80,
216216
tabWidth: 2,
@@ -291,8 +291,8 @@ solutions.
291291
- [`prettier-atom`][atom-plugin] - Atom plugin (check the "ESlint integration"
292292
checkbox in settings)
293293
- [`vs-code-prettier-eslint`][vscode-plugin] - Visual Studio Code plugin
294-
- [`eslint-plugin-prettier`](https://github.com/not-an-aardvark/eslint-plugin-prettier) -
295-
ESLint plugin. While prettier-eslint uses `eslint --fix` to change the output of `prettier`, eslint-plugin-prettier keeps the `prettier` output as-is and integrates it with the regular ESLint workflow.
294+
- [`eslint-plugin-prettier`](https://github.com/prettier/eslint-plugin-prettier) -
295+
ESLint plugin. While `prettier-eslint` uses `eslint --fix` to change the output of `prettier`, `eslint-plugin-prettier` keeps the `prettier` output as-is and integrates it with the regular ESLint workflow.
296296
- [`prettier-eslint-webpack-plugin`](https://github.com/danielterwiel/prettier-eslint-webpack-plugin) -
297297
Prettier ESlint Webpack Plugin
298298

__mocks__/eslint.ts

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/**
2+
* This mock file is so eslint doesn't attempt to actually search around the
3+
* file system for stuff, we can not use `.ts` because it's called by
4+
* `test/fixtures/node_modules/eslint/index.js`
5+
*/
6+
7+
import eslint_, { type ESLint as ESLint_ } from 'eslint';
8+
9+
import type { ESLintLintText, MockESLint } from '../mock.js';
10+
11+
import type { ESLintConfig } from 'prettier-eslint';
12+
13+
const eslint = jest.requireActual<typeof eslint_>('eslint');
14+
15+
const { ESLint } = eslint;
16+
17+
const mockCalculateConfigForFileSpy = jest.fn(mockCalculateConfigForFile);
18+
19+
Object.assign(mockCalculateConfigForFileSpy, { overrides: {} });
20+
21+
const mockLintTextSpy = jest.fn(mockLintText);
22+
23+
export = Object.assign(eslint, {
24+
ESLint: jest.fn(MockESLint),
25+
mock: {
26+
calculateConfigForFile: mockCalculateConfigForFileSpy,
27+
lintText: mockLintTextSpy,
28+
},
29+
});
30+
31+
function MockESLint(options: ESLint_.Options): MockESLint {
32+
globalThis.__PRETTIER_ESLINT_TEST_STATE__.eslintPath = __filename;
33+
const eslintInstance = new ESLint(options) as MockESLint;
34+
eslintInstance.calculateConfigForFile = mockCalculateConfigForFileSpy;
35+
// eslint-disable-next-line @typescript-eslint/unbound-method
36+
eslintInstance._originalLintText = eslintInstance.lintText;
37+
eslintInstance.lintText = mockLintTextSpy;
38+
return eslintInstance;
39+
}
40+
41+
MockESLint.prototype = Object.create(ESLint.prototype) as ESLint_;
42+
43+
/**
44+
* @throws If `throwError` is specifically set on the spy, or if the filePath is
45+
* not handled
46+
*/
47+
// eslint-disable-next-line @typescript-eslint/require-await
48+
async function mockCalculateConfigForFile(
49+
filePath: string,
50+
): Promise<ESLintConfig> {
51+
if (
52+
'throwError' in mockCalculateConfigForFileSpy &&
53+
mockCalculateConfigForFileSpy.throwError instanceof Error
54+
) {
55+
throw mockCalculateConfigForFileSpy.throwError;
56+
}
57+
if (!filePath) {
58+
return {
59+
rules: {},
60+
};
61+
}
62+
if (filePath.includes('default-config')) {
63+
return {
64+
rules: {
65+
semi: [2, 'never'],
66+
'max-len': [2, 120, 2],
67+
indent: [2, 2, { SwitchCase: 1 }],
68+
quotes: [
69+
2,
70+
'single',
71+
{ avoidEscape: true, allowTemplateLiterals: true },
72+
],
73+
'comma-dangle': [
74+
2,
75+
{
76+
arrays: 'always-multiline',
77+
objects: 'always-multiline',
78+
imports: 'always-multiline',
79+
exports: 'always-multiline',
80+
functions: 'always-multiline',
81+
},
82+
],
83+
'arrow-parens': [2, 'as-needed'],
84+
},
85+
};
86+
}
87+
if (filePath.includes('fixtures/paths')) {
88+
return { rules: {} };
89+
}
90+
throw new Error(
91+
`Your mock filePath (${filePath})` +
92+
' does not have a handler for finding the config',
93+
);
94+
}
95+
96+
function mockLintText(this: MockESLint, ...args: Parameters<ESLintLintText>) {
97+
if (
98+
'throwError' in mockLintTextSpy &&
99+
mockLintTextSpy.throwError instanceof Error
100+
) {
101+
throw mockLintTextSpy.throwError;
102+
}
103+
return this._originalLintText(...args);
104+
}

__mocks__/fs.ts

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import type Fs_ from 'node:fs';
2+
3+
type Fs = typeof Fs_;
4+
5+
const fs = jest.requireActual<Fs>('fs');
6+
7+
// eslint-disable-next-line prefer-object-spread -- typing issue
8+
export = Object.assign({}, fs, {
9+
readFileSync: jest.fn((filename: string) => {
10+
if (filename.endsWith('package.json')) {
11+
return '{"name": "fake", "version": "0.0.0", "prettier": {}}';
12+
}
13+
if (/\.[jt]s$/.test(filename)) {
14+
return 'var fake = true';
15+
}
16+
17+
return '';
18+
}),
19+
});

0 commit comments

Comments
 (0)