zap/app/Commands/BuildCommand.php
2025-08-19 18:59:43 -04:00

153 lines
4.4 KiB
PHP

<?php
namespace App\Commands;
use Exception;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Contracts\Cache\Store;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\Facades\Storage;
use LaravelZero\Framework\Commands\Command;
use Illuminate\Support\Str;
use Parsedown;
use function Illuminate\Filesystem\join_paths;
class BuildCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'build';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Build your site. Local is default';
/**
* Execute the console command.
*/
public function handle()
{
// Clear the build directory
// Storage::delete(Storage::disk('build_local')->files());
// Storage::delete(Storage::disk('build_local')->directories());
$ignored = [
"assets",
"_"
];
$files = Storage::disk('source')->files(recursive: true);
foreach ($ignored as $ignore) {
$files = array_filter($files, fn($path) => !str_starts_with($path, $ignore));
}
$pages = [];
// Set up a structure
foreach ($files as $f) {
$pages[] = [
'path' => $f,
'name' => basename($f),
'source' => Storage::disk('source')->path($f),
'output_path' => $this->getOutputPath($f),
'extension' => $this->getFileExtension($f)
];
}
// Parse and output
foreach ($pages as $p) {
try {
if ($p['extension'] == 'blade.php') {
$rendered = $this->renderBlade($p);
} else {
$rendered = $this->renderMarkdown($p);
}
} catch (Exception $e) {
$this->error("Failed on: " . $p['path']);
throw $e;
}
Storage::disk('build_local')->put($p['output_path'], $rendered);
}
// Copy static assets folder
foreach (Storage::disk('source')->allFiles('assets/static') as $asset) {
$targetPath = str($asset)->replace("assets/static", "assets")->toString();
// Use Storage facade for both source and target
$content = Storage::disk('source')->get($asset);
Storage::disk('build_local')->put($targetPath, $content);
}
$this->info("Site built");
$this->notify("Site Zapped", "Your site has been built");
}
public function renderBlade(array $page): string
{
$blade = file_get_contents($page['source']);
return Blade::render($blade, []);
}
public function renderMarkdown(array $page): string
{
$parser = new Parsedown();
$md = file_get_contents($page['source']);
$parsed = $parser->text($md);
$tmpBlade = <<<HTML
<x-layouts.main>
$parsed
</x-layouts.main>
HTML;
$rendered = Blade::render($tmpBlade, []);
return $rendered;
}
public function getFileExtension($filename): string
{
// Check for .blade.php first
if (str_ends_with($filename, '.blade.php')) {
return 'blade.php';
}
// Fall back to regular extension
return pathinfo($filename, PATHINFO_EXTENSION);
}
public function slugFromFilename(string $filename): string
{
return Str::of(basename($filename))->remove(".md")->remove(".blade.php")->slug()->toString();
}
public function titleFromFilename(string $filename): string
{
return Str::of(basename($filename))->remove(".md")->remove(".blade.php")->replace('-', ' ')->title()->toString();
}
public function getOutputPath(string $filename): string
{
$indexFiles = ['index.md', 'index.blade.php'];
$baseDirectory = Str::of($filename)->remove(basename($filename))->trim('/')->toString();
if (in_array(basename($filename), $indexFiles)) {
return join_paths($baseDirectory, "index.html");
}
return join_paths($baseDirectory, "{$this->slugFromFilename($filename)}", "index.html");
}
/**
* Define the command's schedule.
*/
public function schedule(Schedule $schedule): void
{
// $schedule->command(static::class)->everyMinute();
}
}