Skip to content

Commit 6f41572

Browse files
authored
[2.x] Add option to install ESLint with Prettier (#412)
* add stub for eslint config * add stub for prettier config * add option to install eslint with prettier * fix lint errors * add CI workflow to fix code styling * delete style ci config * replace prettier.config.cjs with .prettierrc * Pint: fix code styling * ESLint: fix code styling * format --------- Co-authored-by: avosalmon <[email protected]>
1 parent 79f0661 commit 6f41572

File tree

130 files changed

+2159
-708
lines changed

Some content is hidden

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

130 files changed

+2159
-708
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
name: fix code styling
2+
3+
on: [push]
4+
5+
jobs:
6+
pint:
7+
uses: laravel/.github/.github/workflows/coding-standards.yml@main
8+
with:
9+
message: "Pint: fix code styling"
10+
11+
eslint:
12+
name: Lint stubs for Inertia stacks
13+
runs-on: ubuntu-latest
14+
needs: pint
15+
16+
steps:
17+
- name: Checkout code
18+
uses: actions/checkout@v4
19+
20+
# We need to pull the latest changes because the `pint` job might have pushed changes
21+
- name: Pull Remote Changes
22+
run: git pull
23+
24+
- uses: actions/setup-node@v4
25+
with:
26+
node-version: 20
27+
28+
- name: Install NPM packages
29+
run: |
30+
# Common packages
31+
npm install \
32+
eslint@^8.57.0 \
33+
prettier@^3.3.0 \
34+
prettier-plugin-organize-imports@^4.0.0 \
35+
prettier-plugin-tailwindcss@^0.6.5
36+
37+
# React
38+
npm install \
39+
react@^18.2.0 \
40+
eslint-plugin-react@^7.34.4 \
41+
eslint-plugin-react-hooks@^4.6.2 \
42+
eslint-plugin-prettier@^5.1.3 \
43+
eslint-config-prettier@^9.1.0 \
44+
@typescript-eslint/eslint-plugin@^7.16.0 \
45+
@typescript-eslint/parser@^7.16.0
46+
47+
# Vue
48+
npm install \
49+
eslint-plugin-vue@^9.23.0 \
50+
@rushstack/eslint-patch@^1.8.0 \
51+
@vue/eslint-config-prettier@^9.0.0 \
52+
@vue/eslint-config-typescript@^13.0.0
53+
54+
- name: Run ESLint
55+
run: |
56+
cp stubs/inertia-common/.prettierrc .
57+
npx eslint --config stubs/inertia-react/.eslintrc.json stubs/inertia-react/resources/js --ext .js,.jsx --fix
58+
npx eslint --config stubs/inertia-react-ts/.eslintrc.json stubs/inertia-react-ts/resources/js --ext .js,.jsx,.ts,.tsx --fix
59+
npx eslint --config stubs/inertia-vue/.eslintrc.cjs stubs/inertia-vue/resources/js --ext .js,.vue --fix
60+
npx eslint --config stubs/inertia-vue-ts/.eslintrc.cjs stubs/inertia-vue-ts/resources/js --ext .js,.ts,.vue --fix
61+
62+
- name: Clean up
63+
run: rm -rf node_modules package.json package-lock.json .prettierrc
64+
65+
- name: Commit changes
66+
uses: stefanzweifel/git-auto-commit-action@v5
67+
with:
68+
commit_message: "ESLint: fix code styling"

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ on:
1111

1212
jobs:
1313
stub-tests:
14-
runs-on: ubuntu-22.04
14+
runs-on: ubuntu-latest
1515

1616
strategy:
1717
fail-fast: true

.styleci.yml

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/Console/InstallCommand.php

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class InstallCommand extends Command implements PromptsForMissingInput
3434
{--pest : Indicate that Pest should be installed}
3535
{--ssr : Indicates if Inertia SSR support should be installed}
3636
{--typescript : Indicates if TypeScript is preferred for the Inertia stack}
37+
{--eslint : Indicates if ESLint with Prettier should be installed}
3738
{--composer=global : Absolute path to the Composer binary which should be used to install packages}';
3839

3940
/**
@@ -181,7 +182,6 @@ protected function hasComposerPackage($package)
181182
/**
182183
* Installs the given Composer Packages into the application.
183184
*
184-
* @param array $packages
185185
* @param bool $asDev
186186
* @return bool
187187
*/
@@ -209,7 +209,6 @@ protected function requireComposerPackages(array $packages, $asDev = false)
209209
/**
210210
* Removes the given Composer Packages from the application.
211211
*
212-
* @param array $packages
213212
* @param bool $asDev
214213
* @return bool
215214
*/
@@ -235,9 +234,8 @@ protected function removeComposerPackages(array $packages, $asDev = false)
235234
}
236235

237236
/**
238-
* Update the "package.json" file.
237+
* Update the dependencies in the "package.json" file.
239238
*
240-
* @param callable $callback
241239
* @param bool $dev
242240
* @return void
243241
*/
@@ -264,6 +262,29 @@ protected static function updateNodePackages(callable $callback, $dev = true)
264262
);
265263
}
266264

265+
/**
266+
* Update the scripts in the "package.json" file.
267+
*
268+
* @return void
269+
*/
270+
protected static function updateNodeScripts(callable $callback)
271+
{
272+
if (! file_exists(base_path('package.json'))) {
273+
return;
274+
}
275+
276+
$content = json_decode(file_get_contents(base_path('package.json')), true);
277+
278+
$content['scripts'] = $callback(
279+
array_key_exists('scripts', $content) ? $content['scripts'] : []
280+
);
281+
282+
file_put_contents(
283+
base_path('package.json'),
284+
json_encode($content, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT).PHP_EOL
285+
);
286+
}
287+
267288
/**
268289
* Delete the "node_modules" directory and remove the associated lock files.
269290
*
@@ -302,7 +323,7 @@ protected function replaceInFile($search, $replace, $path)
302323
*/
303324
protected function phpBinary()
304325
{
305-
return (new PhpExecutableFinder())->find(false) ?: 'php';
326+
return (new PhpExecutableFinder)->find(false) ?: 'php';
306327
}
307328

308329
/**
@@ -331,7 +352,6 @@ protected function runCommands($commands)
331352
/**
332353
* Remove Tailwind dark classes from the given files.
333354
*
334-
* @param \Symfony\Component\Finder\Finder $finder
335355
* @return void
336356
*/
337357
protected function removeDarkClasses(Finder $finder)
@@ -367,8 +387,6 @@ protected function promptForMissingArgumentsUsing()
367387
/**
368388
* Interact further with the user if they were prompted for missing arguments.
369389
*
370-
* @param \Symfony\Component\Console\Input\InputInterface $input
371-
* @param \Symfony\Component\Console\Output\OutputInterface $output
372390
* @return void
373391
*/
374392
protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output)
@@ -382,6 +400,7 @@ protected function afterPromptingForMissingArguments(InputInterface $input, Outp
382400
'dark' => 'Dark mode',
383401
'ssr' => 'Inertia SSR',
384402
'typescript' => 'TypeScript',
403+
'eslint' => 'ESLint with Prettier',
385404
]
386405
))->each(fn ($option) => $input->setOption($option, true));
387406
} elseif (in_array($stack, ['blade', 'livewire', 'livewire-functional'])) {

src/Console/InstallsInertiaStacks.php

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,46 @@ protected function installInertiaVueStack()
4141
});
4242
}
4343

44+
if ($this->option('eslint')) {
45+
$this->updateNodePackages(function ($packages) {
46+
return [
47+
'eslint' => '^8.57.0',
48+
'eslint-plugin-vue' => '^9.23.0',
49+
'@rushstack/eslint-patch' => '^1.8.0',
50+
'@vue/eslint-config-prettier' => '^9.0.0',
51+
'prettier' => '^3.3.0',
52+
'prettier-plugin-organize-imports' => '^4.0.0',
53+
'prettier-plugin-tailwindcss' => '^0.6.5',
54+
] + $packages;
55+
});
56+
57+
if ($this->option('typescript')) {
58+
$this->updateNodePackages(function ($packages) {
59+
return [
60+
'@vue/eslint-config-typescript' => '^13.0.0',
61+
] + $packages;
62+
});
63+
64+
$this->updateNodeScripts(function ($scripts) {
65+
return $scripts + [
66+
'lint' => 'eslint resources/js --ext .js,.ts,.vue --ignore-path .gitignore --fix',
67+
];
68+
});
69+
70+
copy(__DIR__.'/../../stubs/inertia-vue-ts/.eslintrc.cjs', base_path('.eslintrc.cjs'));
71+
} else {
72+
$this->updateNodeScripts(function ($scripts) {
73+
return $scripts + [
74+
'lint' => 'eslint resources/js --ext .js,.vue --ignore-path .gitignore --fix',
75+
];
76+
});
77+
78+
copy(__DIR__.'/../../stubs/inertia-vue/.eslintrc.cjs', base_path('.eslintrc.cjs'));
79+
}
80+
81+
copy(__DIR__.'/../../stubs/inertia-common/.prettierrc', base_path('.prettierrc'));
82+
}
83+
4484
// Providers...
4585
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/inertia-common/app/Providers', app_path('Providers'));
4686

@@ -216,6 +256,48 @@ protected function installInertiaReactStack()
216256
});
217257
}
218258

259+
if ($this->option('eslint')) {
260+
$this->updateNodePackages(function ($packages) {
261+
return [
262+
'eslint' => '^8.57.0',
263+
'eslint-plugin-react' => '^7.34.4',
264+
'eslint-plugin-react-hooks' => '^4.6.2',
265+
'eslint-plugin-prettier' => '^5.1.3',
266+
'eslint-config-prettier' => '^9.1.0',
267+
'prettier' => '^3.3.0',
268+
'prettier-plugin-organize-imports' => '^4.0.0',
269+
'prettier-plugin-tailwindcss' => '^0.6.5',
270+
] + $packages;
271+
});
272+
273+
if ($this->option('typescript')) {
274+
$this->updateNodePackages(function ($packages) {
275+
return [
276+
'@typescript-eslint/eslint-plugin' => '^7.16.0',
277+
'@typescript-eslint/parser' => '^7.16.0',
278+
] + $packages;
279+
});
280+
281+
$this->updateNodeScripts(function ($scripts) {
282+
return $scripts + [
283+
'lint' => 'eslint resources/js --ext .js,.jsx,.ts,.tsx --ignore-path .gitignore --fix',
284+
];
285+
});
286+
287+
copy(__DIR__.'/../../stubs/inertia-react-ts/.eslintrc.json', base_path('.eslintrc.json'));
288+
} else {
289+
$this->updateNodeScripts(function ($scripts) {
290+
return $scripts + [
291+
'lint' => 'eslint resources/js --ext .js,.jsx --ignore-path .gitignore --fix',
292+
];
293+
});
294+
295+
copy(__DIR__.'/../../stubs/inertia-react/.eslintrc.json', base_path('.eslintrc.json'));
296+
}
297+
298+
copy(__DIR__.'/../../stubs/inertia-common/.prettierrc', base_path('.prettierrc'));
299+
}
300+
219301
// Providers...
220302
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/inertia-common/app/Providers', app_path('Providers'));
221303

stubs/api/routes/auth.php

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,29 @@
99
use Illuminate\Support\Facades\Route;
1010

1111
Route::post('/register', [RegisteredUserController::class, 'store'])
12-
->middleware('guest')
13-
->name('register');
12+
->middleware('guest')
13+
->name('register');
1414

1515
Route::post('/login', [AuthenticatedSessionController::class, 'store'])
16-
->middleware('guest')
17-
->name('login');
16+
->middleware('guest')
17+
->name('login');
1818

1919
Route::post('/forgot-password', [PasswordResetLinkController::class, 'store'])
20-
->middleware('guest')
21-
->name('password.email');
20+
->middleware('guest')
21+
->name('password.email');
2222

2323
Route::post('/reset-password', [NewPasswordController::class, 'store'])
24-
->middleware('guest')
25-
->name('password.store');
24+
->middleware('guest')
25+
->name('password.store');
2626

2727
Route::get('/verify-email/{id}/{hash}', VerifyEmailController::class)
28-
->middleware(['auth', 'signed', 'throttle:6,1'])
29-
->name('verification.verify');
28+
->middleware(['auth', 'signed', 'throttle:6,1'])
29+
->name('verification.verify');
3030

3131
Route::post('/email/verification-notification', [EmailVerificationNotificationController::class, 'store'])
32-
->middleware(['auth', 'throttle:6,1'])
33-
->name('verification.send');
32+
->middleware(['auth', 'throttle:6,1'])
33+
->name('verification.send');
3434

3535
Route::post('/logout', [AuthenticatedSessionController::class, 'destroy'])
36-
->middleware('auth')
37-
->name('logout');
36+
->middleware('auth')
37+
->name('logout');

stubs/default/app/Http/Controllers/Auth/NewPasswordController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,6 @@ function ($user) use ($request) {
5656
return $status == Password::PASSWORD_RESET
5757
? redirect()->route('login')->with('status', __($status))
5858
: back()->withInput($request->only('email'))
59-
->withErrors(['email' => __($status)]);
59+
->withErrors(['email' => __($status)]);
6060
}
6161
}

stubs/default/app/Http/Controllers/Auth/PasswordResetLinkController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,6 @@ public function store(Request $request): RedirectResponse
3939
return $status == Password::RESET_LINK_SENT
4040
? back()->with('status', __($status))
4141
: back()->withInput($request->only('email'))
42-
->withErrors(['email' => __($status)]);
42+
->withErrors(['email' => __($status)]);
4343
}
4444
}

0 commit comments

Comments
 (0)