Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
62 / 62 |
|
100.00% |
8 / 8 |
CRAP | |
100.00% |
1 / 1 |
BuildSiteCommand | |
100.00% |
62 / 62 |
|
100.00% |
8 / 8 |
17 | |
100.00% |
1 / 1 |
handle | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
1 | |||
configureBuildTaskService | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
runPreBuildActions | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
3 | |||
runPostBuildActions | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
4 | |||
printFinishMessage | |
100.00% |
17 / 17 |
|
100.00% |
1 / 1 |
2 | |||
runNodeCommand | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
hasWarnings | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
getExitCode | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
3 |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Hyde\Console\Commands; |
6 | |
7 | use Hyde\Hyde; |
8 | use Hyde\Facades\Config; |
9 | use Hyde\Support\BuildWarnings; |
10 | use Hyde\Console\Concerns\Command; |
11 | use Hyde\Framework\Services\BuildService; |
12 | use Hyde\Framework\Services\BuildTaskService; |
13 | use Illuminate\Support\Facades\Process; |
14 | |
15 | use function memory_get_peak_usage; |
16 | use function number_format; |
17 | use function array_search; |
18 | use function microtime; |
19 | use function sprintf; |
20 | use function app; |
21 | |
22 | /** |
23 | * Run the static site build process. |
24 | */ |
25 | class BuildSiteCommand extends Command |
26 | { |
27 | /** @var string */ |
28 | protected $signature = 'build |
29 | {--run-dev : Run the NPM dev script after build} |
30 | {--run-prod : Run the NPM prod script after build} |
31 | {--run-prettier : Format the output using NPM Prettier} |
32 | {--pretty-urls : Should links in output use pretty URLs?} |
33 | {--no-api : Disable API calls, for example, Torchlight}'; |
34 | |
35 | /** @var string */ |
36 | protected $description = 'Build the static site'; |
37 | |
38 | protected BuildService $service; |
39 | protected BuildTaskService $taskService; |
40 | |
41 | public function handle(): int |
42 | { |
43 | $timeStart = microtime(true); |
44 | |
45 | $this->title('Building your static site!'); |
46 | |
47 | $this->service = new BuildService($this->output); |
48 | |
49 | $this->configureBuildTaskService(); |
50 | |
51 | $this->runPreBuildActions(); |
52 | |
53 | $this->service->transferMediaAssets(); |
54 | |
55 | $this->service->compileStaticPages(); |
56 | |
57 | $this->runPostBuildActions(); |
58 | |
59 | $this->printFinishMessage($timeStart); |
60 | |
61 | return $this->getExitCode(); |
62 | } |
63 | |
64 | protected function configureBuildTaskService(): void |
65 | { |
66 | /** @var BuildTaskService $taskService */ |
67 | $taskService = app(BuildTaskService::class); |
68 | |
69 | $this->taskService = $taskService; |
70 | $this->taskService->setOutput($this->output); |
71 | } |
72 | |
73 | protected function runPreBuildActions(): void |
74 | { |
75 | if ($this->option('no-api')) { |
76 | $this->info('Disabling external API calls'); |
77 | $this->newLine(); |
78 | /** @var array<string, string> $config */ |
79 | $config = Config::getArray('hyde.features', []); |
80 | unset($config[array_search('torchlight', $config)]); |
81 | Config::set(['hyde.features' => $config]); |
82 | } |
83 | |
84 | if ($this->option('pretty-urls')) { |
85 | $this->info('Generating site with pretty URLs'); |
86 | $this->newLine(); |
87 | Config::set(['hyde.pretty_urls' => true]); |
88 | } |
89 | |
90 | $this->taskService->runPreBuildTasks(); |
91 | } |
92 | |
93 | public function runPostBuildActions(): void |
94 | { |
95 | $this->taskService->runPostBuildTasks(); |
96 | |
97 | if ($this->option('run-prettier')) { |
98 | $this->runNodeCommand( |
99 | 'npx prettier '.Hyde::pathToRelative(Hyde::sitePath()).'/**/*.html --write --bracket-same-line', |
100 | 'Prettifying code!', |
101 | 'prettify code' |
102 | ); |
103 | } |
104 | |
105 | if ($this->option('run-dev')) { |
106 | $this->runNodeCommand('npm run dev', 'Building frontend assets for development!'); |
107 | } |
108 | |
109 | if ($this->option('run-prod')) { |
110 | $this->runNodeCommand('npm run prod', 'Building frontend assets for production!'); |
111 | } |
112 | } |
113 | |
114 | protected function printFinishMessage(float $timeStart): void |
115 | { |
116 | if ($this->hasWarnings()) { |
117 | $this->newLine(); |
118 | $this->error('There were some warnings during the build process:'); |
119 | $this->newLine(); |
120 | BuildWarnings::writeWarningsToOutput($this->output, $this->output->isVerbose()); |
121 | } |
122 | |
123 | $executionTime = (microtime(true) - $timeStart); |
124 | $this->info(sprintf( |
125 | "\nAll done! Finished in %s seconds (%sms) with %sMB peak memory usage", |
126 | number_format($executionTime, 2), |
127 | number_format($executionTime * 1000, 2), |
128 | number_format(memory_get_peak_usage() / 1024 / 1024, 2) |
129 | )); |
130 | |
131 | $this->info('Congratulations! 🎉 Your static site has been built!'); |
132 | $this->line( |
133 | 'Your new homepage is stored here -> '. |
134 | static::fileLink(Hyde::sitePath('index.html')) |
135 | ); |
136 | } |
137 | |
138 | protected function runNodeCommand(string $command, string $message, ?string $actionMessage = null): void |
139 | { |
140 | $this->info($message.' This may take a second.'); |
141 | |
142 | $output = Process::command($command)->run(); |
143 | |
144 | $this->line($output->output() ?? sprintf( |
145 | '<fg=red>Could not %s! Is NPM installed?</>', |
146 | $actionMessage ?? 'run script' |
147 | )); |
148 | } |
149 | |
150 | protected function hasWarnings(): bool |
151 | { |
152 | return BuildWarnings::hasWarnings() && BuildWarnings::reportsWarnings(); |
153 | } |
154 | |
155 | protected function getExitCode(): int |
156 | { |
157 | if ($this->hasWarnings() && BuildWarnings::reportsWarningsAsExceptions()) { |
158 | return Command::INVALID; |
159 | } |
160 | |
161 | return Command::SUCCESS; |
162 | } |
163 | } |