Skip to content

Commit 9f58d63

Browse files
committed
Tweaks the install command
1 parent af67f39 commit 9f58d63

File tree

1 file changed

+167
-22
lines changed

1 file changed

+167
-22
lines changed

src/Commands/InstallCommand.php

Lines changed: 167 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use Illuminate\Console\Command;
66
use Illuminate\Support\Facades\File;
7-
use Illuminate\Support\Str;
7+
use Symfony\Component\Console\Terminal;
88

99
class InstallCommand extends Command
1010
{
@@ -16,47 +16,192 @@ class InstallCommand extends Command
1616

1717
protected $description = 'Installs the Tailwind CSS scaffolding for new Laravel applications.';
1818

19+
private $afterMessages = [];
20+
1921
public function handle()
2022
{
21-
$this->info('Installing the Tailwind CSS scaffolding...');
23+
$this->displayHeader('Installing TailwindCSS Laravel', '<bg=blue;fg=black> INFO </>');
2224

23-
$this->copyStubToAppIfMissing(
24-
stub: __DIR__ . '/../../stubs/tailwind.config.js',
25-
to: base_path('tailwind.config.js'),
26-
);
25+
$this->ensureTailwindConfigExists();
26+
$this->ensureTailwindCliBinaryExists();
27+
$this->addImportStylesToLayouts();
28+
$this->addIngoreLines();
29+
$this->runFirstBuild();
2730

28-
$this->copyStubToAppIfMissing(
29-
stub: __DIR__ . '/../../stubs/resources/css/app.css',
30-
to: resource_path('css/app.css'),
31-
);
31+
$this->displayAfterNotes();
3232

33-
if ($this->option('download')) {
34-
$this->call('tailwindcss:download', [
35-
'--cli-version' => $this->option('cli-version') ?: config('tailwindcss.version'),
36-
]);
37-
} else {
38-
$this->info('Done!');
39-
}
33+
$this->newLine();
34+
$this->line(' <fg=white>Done!</>');
4035

4136
return self::SUCCESS;
4237
}
4338

39+
private function ensureTailwindConfigExists()
40+
{
41+
$this->displayTask('ensuring tailwind.config.js exists', function () {
42+
$this->copyStubToAppIfMissing(
43+
stub: __DIR__ . '/../../stubs/tailwind.config.js',
44+
to: base_path('tailwind.config.js'),
45+
);
46+
47+
$this->copyStubToAppIfMissing(
48+
stub: __DIR__ . '/../../stubs/resources/css/app.css',
49+
to: resource_path('css/app.css'),
50+
);
51+
52+
return self::SUCCESS;
53+
});
54+
}
55+
56+
private function ensureTailwindCliBinaryExists()
57+
{
58+
if (! File::exists(config('tailwindcss.bin_path')) || $this->option('download')) {
59+
$this->displayTask('downloading the Tailwind CLI binary', function () {
60+
return $this->callSilently('tailwindcss:download', [
61+
'--cli-version' => $this->option('cli-version') ?: config('tailwindcss.version'),
62+
]);
63+
});
64+
}
65+
}
66+
4467
private function copyStubToAppIfMissing(string $stub, string $to): void
4568
{
4669
if (File::exists($to)) {
47-
$this->warn(sprintf(" File %s already exists.", $this->relativeOf($to)));
48-
4970
return;
5071
}
5172

5273
File::ensureDirectoryExists(dirname($to));
5374
File::copy($stub, $to);
75+
}
5476

55-
$this->info(sprintf(" Created the %s file.", $this->relativeOf($to)));
77+
private function displayTask($description, $task)
78+
{
79+
$width = (new Terminal())->getWidth();
80+
$dots = max(str_repeat('<fg=gray>.</>', $width - strlen($description) - 13), 0);
81+
$this->output->write(sprintf(' <fg=white>%s</> %s ', $description, $dots));
82+
$output = $task();
83+
84+
if ($output === self::SUCCESS) {
85+
$this->output->write('<info>DONE</info>');
86+
} elseif ($output === self::FAILURE) {
87+
$this->output->write('<error>FAIL</error>');
88+
} elseif ($output === self::INVALID) {
89+
$this->output->write('<fg=yellow>WARN</>');
90+
}
91+
92+
$this->newLine();
93+
}
94+
95+
private function displayHeader($text, $prefix)
96+
{
97+
$this->newLine();
98+
$this->line(sprintf(' %s <fg=white>%s</> ', $prefix, $text));
99+
$this->newLine();
56100
}
57101

58-
private function relativeOf(string $path): string
102+
private function addImportStylesToLayouts()
59103
{
60-
return Str::after($path, rtrim(base_path(), '/') . '/');
104+
$this->displayTask('updating layouts', function () {
105+
if (File::exists(base_path('webpack.mix.js'))) {
106+
$this->replaceMixStylesToLayouts();
107+
} elseif (File::exists(base_path('vite.config.js'))) {
108+
$this->replaceViteStylesToLayouts();
109+
} else {
110+
$this->appendTailwindStylesToLayouts();
111+
}
112+
113+
return self::SUCCESS;
114+
});
115+
}
116+
117+
private function replaceMixStylesToLayouts()
118+
{
119+
$this->existingLayouts()
120+
->each(fn ($file) => File::put(
121+
$file,
122+
str_replace(
123+
"mix('css/app.css')",
124+
"tailwindcss('css/app.css')",
125+
File::get($file),
126+
),
127+
));
128+
}
129+
130+
private function replaceViteStylesToLayouts()
131+
{
132+
$this->existingLayouts()
133+
->each(fn ($file) => File::put(
134+
$file,
135+
preg_replace(
136+
'/\@vite\(\[\'resources\/css\/app.css\', \'resources\/js\/app.js\'\]\)/',
137+
"@vite(['resources/js/app.js'])",
138+
File::get($file),
139+
),
140+
));
141+
142+
$this->appendTailwindStylesToLayouts();
143+
}
144+
145+
private function appendTailwindStylesToLayouts()
146+
{
147+
$this->existingLayoutFiles()
148+
->each(fn ($file) => File::put(
149+
$file,
150+
preg_replace(
151+
'/(\s*)(<\/head>)/',
152+
"\\1 <link rel=\"stylesheet\" href=\"{{ tailwindcss('css/app.css') }}\">\n\\1\\2",
153+
File::get($file),
154+
),
155+
));
156+
}
157+
158+
private function existingLayoutFiles()
159+
{
160+
return collect(['app', 'guest'])
161+
->map(fn ($file) => resource_path("views/layouts/{$file}.blade.php"))
162+
->filter(fn ($file) => File::exists($file));
163+
}
164+
165+
private function addIngoreLines()
166+
{
167+
$this->displayTask('adding ignore lines', function () {
168+
$binary = basename(config('tailwindcss.bin_path'));
169+
170+
File::append(base_path('.gitignore'), <<<LINES
171+
172+
/public/css/
173+
/public/dist/
174+
.tailwindcss-manifest.json
175+
{$binary}
176+
LINES);
177+
178+
return self::SUCCESS;
179+
});
180+
}
181+
182+
private function runFirstBuild()
183+
{
184+
$this->displayTask('running first build', function () {
185+
$result = $this->callSilently('tailwindcss:build');
186+
187+
if ($result !== self::SUCCESS) {
188+
$this->afterMessages[] = '<fg=white>* Try running `<fg=yellow>php artisan tailwindcss:build</>`</>';
189+
190+
return self::INVALID;
191+
}
192+
193+
return self::SUCCESS;
194+
});
195+
}
196+
197+
private function displayAfterNotes()
198+
{
199+
if (count($this->afterMessages) > 0) {
200+
$this->displayHeader('After Notes & Next Steps', '<bg=yellow;fg=black> NOTES </>');
201+
202+
foreach ($this->afterMessages as $message) {
203+
$this->line(' '.$message);
204+
}
205+
}
61206
}
62207
}

0 commit comments

Comments
 (0)