events werden nun erfolgreich gespeichert, branding wird nun erfolgreich gespeichert, emotionen können nun angelegt werden. Task Ansicht im Event admin verbessert, Buttons in FAB umgewandelt und vereinheitlicht. Teilen-Link Guest PWA schicker gemacht, SynGoogleFonts ausgebaut (mit Einzel-Family-Download).
This commit is contained in:
@@ -6,13 +6,13 @@ use Illuminate\Console\Command;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class SyncGoogleFonts extends Command
|
||||
{
|
||||
protected $signature = 'fonts:sync-google {--count=50 : Number of popular fonts to fetch} {--weights=400,700 : Comma separated numeric font weights to download} {--italic : Also download italic variants where available} {--force : Re-download files even if they exist} {--path= : Optional custom output directory (defaults to public/fonts/google)}';
|
||||
protected $signature = 'fonts:sync-google {--count=50 : Number of popular fonts to fetch} {--weights=400,700 : Comma separated numeric font weights to download} {--italic : Also download italic variants where available} {--force : Re-download files even if they exist} {--path= : Optional custom output directory (defaults to public/fonts/google)} {--family= : Download a single family by name (case-insensitive)} {--category= : Filter by category, comma separated (e.g. sans-serif,serif)} {--dry-run : Show what would be downloaded without writing files}';
|
||||
|
||||
protected $description = 'Download the most popular Google Fonts to the local public/fonts/google directory and generate a manifest + CSS file.';
|
||||
|
||||
@@ -32,13 +32,28 @@ class SyncGoogleFonts extends Command
|
||||
$weights = $this->prepareWeights($this->option('weights'));
|
||||
$includeItalic = (bool) $this->option('italic');
|
||||
$force = (bool) $this->option('force');
|
||||
$dryRun = (bool) $this->option('dry-run');
|
||||
$familyOption = $this->normalizeFamilyOption($this->option('family'));
|
||||
$categories = $this->prepareCategories($this->option('category'));
|
||||
|
||||
$pathOption = $this->option('path');
|
||||
$basePath = $pathOption
|
||||
? (Str::startsWith($pathOption, DIRECTORY_SEPARATOR) ? $pathOption : base_path($pathOption))
|
||||
: public_path('fonts/google');
|
||||
|
||||
$this->info(sprintf('Fetching top %d Google Fonts (weights: %s, italic: %s)...', $count, implode(', ', $weights), $includeItalic ? 'yes' : 'no'));
|
||||
if ($familyOption) {
|
||||
$this->info(sprintf('Fetching Google Font family "%s" (weights: %s, italic: %s)...', $familyOption, implode(', ', $weights), $includeItalic ? 'yes' : 'no'));
|
||||
} else {
|
||||
$this->info(sprintf('Fetching top %d Google Fonts (weights: %s, italic: %s)...', $count, implode(', ', $weights), $includeItalic ? 'yes' : 'no'));
|
||||
}
|
||||
|
||||
if (count($categories)) {
|
||||
$this->line('Category filter: '.implode(', ', $categories));
|
||||
}
|
||||
|
||||
if ($dryRun) {
|
||||
$this->warn('Dry run enabled: no files will be written.');
|
||||
}
|
||||
|
||||
$response = Http::retry(2, 200)
|
||||
->timeout(30)
|
||||
@@ -60,10 +75,27 @@ class SyncGoogleFonts extends Command
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
$selected = array_slice($items, 0, $count);
|
||||
$items = $this->filterFonts($items, $familyOption, $categories);
|
||||
|
||||
if ($familyOption && ! count($items)) {
|
||||
$this->error(sprintf('Font family "%s" was not found.', $familyOption));
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
if (! count($items)) {
|
||||
$this->warn('No fonts matched the provided filters.');
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
$selected = $familyOption ? $items : array_slice($items, 0, $count);
|
||||
$manifestFonts = [];
|
||||
$filesystem = new Filesystem();
|
||||
File::ensureDirectoryExists($basePath);
|
||||
$filesystem = new Filesystem;
|
||||
|
||||
if (! $dryRun) {
|
||||
File::ensureDirectoryExists($basePath);
|
||||
}
|
||||
|
||||
foreach ($selected as $index => $font) {
|
||||
if (! is_array($font) || ! isset($font['family'])) {
|
||||
@@ -73,11 +105,14 @@ class SyncGoogleFonts extends Command
|
||||
$family = (string) $font['family'];
|
||||
$slug = Str::slug($family);
|
||||
$familyDir = $basePath.DIRECTORY_SEPARATOR.$slug;
|
||||
File::ensureDirectoryExists($familyDir);
|
||||
if (! $dryRun) {
|
||||
File::ensureDirectoryExists($familyDir);
|
||||
}
|
||||
|
||||
$variantMap = $this->buildVariantMap($font, $weights, $includeItalic);
|
||||
if (! count($variantMap)) {
|
||||
$this->warn("Skipping {$family} (no matching variants)");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -89,7 +124,11 @@ class SyncGoogleFonts extends Command
|
||||
$filename = sprintf('%s-%s-%s.%s', Str::studly($slug), $weight, $style, $extension);
|
||||
$targetPath = $familyDir.DIRECTORY_SEPARATOR.$filename;
|
||||
|
||||
if (! $force && $filesystem->exists($targetPath)) {
|
||||
$alreadyExists = $filesystem->exists($targetPath);
|
||||
|
||||
if ($dryRun) {
|
||||
$this->line(sprintf('◦ DRY RUN: %s %s would %s (%s)', $family, $variantKey, $alreadyExists && ! $force ? 'reuse existing file' : 'download', $targetPath));
|
||||
} elseif (! $force && $alreadyExists) {
|
||||
$this->line("✔ {$family} {$variantKey} already exists");
|
||||
} else {
|
||||
$this->line("↓ Downloading {$family} {$variantKey}");
|
||||
@@ -97,6 +136,7 @@ class SyncGoogleFonts extends Command
|
||||
|
||||
if (! $fileResponse->ok()) {
|
||||
$this->warn(" Skipped {$family} {$variantKey} (download failed)");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -124,6 +164,12 @@ class SyncGoogleFonts extends Command
|
||||
];
|
||||
}
|
||||
|
||||
if ($dryRun) {
|
||||
$this->info(sprintf('Dry run complete: %d font families would be synced to %s', count($manifestFonts), $basePath));
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
$this->pruneStaleFamilies($basePath, $manifestFonts);
|
||||
$this->writeManifest($basePath, $manifestFonts);
|
||||
$this->writeCss($basePath, $manifestFonts);
|
||||
@@ -134,6 +180,54 @@ class SyncGoogleFonts extends Command
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
private function normalizeFamilyOption(?string $family): ?string
|
||||
{
|
||||
$family = trim((string) $family);
|
||||
|
||||
return $family !== '' ? $family : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, string>
|
||||
*/
|
||||
private function prepareCategories(?string $categories): array
|
||||
{
|
||||
$parts = array_filter(array_map('trim', explode(',', (string) $categories)));
|
||||
|
||||
return array_values(array_unique(array_map(static function ($category) {
|
||||
$normalized = Str::of($category)->lower()->replace(' ', '-')->toString();
|
||||
|
||||
return (string) $normalized;
|
||||
}, $parts)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, mixed> $items
|
||||
* @return array<int, mixed>
|
||||
*/
|
||||
private function filterFonts(array $items, ?string $family, array $categories): array
|
||||
{
|
||||
$filtered = collect($items)
|
||||
->filter(fn ($font) => is_array($font) && isset($font['family']))
|
||||
->filter(function ($font) use ($categories) {
|
||||
if (! count($categories)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$category = strtolower((string) ($font['category'] ?? ''));
|
||||
|
||||
return in_array($category, $categories, true);
|
||||
});
|
||||
|
||||
if ($family) {
|
||||
$filtered = $filtered->filter(function ($font) use ($family) {
|
||||
return strcasecmp((string) $font['family'], $family) === 0;
|
||||
});
|
||||
}
|
||||
|
||||
return $filtered->values()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, int>
|
||||
*/
|
||||
@@ -147,7 +241,7 @@ class SyncGoogleFonts extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $font
|
||||
* @param array<string, mixed> $font
|
||||
* @return array<string, string>
|
||||
*/
|
||||
private function buildVariantMap(array $font, array $weights, bool $includeItalic): array
|
||||
|
||||
Reference in New Issue
Block a user