mirror of
https://github.com/HolgerHatGarKeineNode/einundzwanzig-nostr.git
synced 2026-04-09 13:28:42 +00:00
- 🛠 Introduce `RichTextMarkdownNormalizer` to convert Markdown and mixed input to cleaner HTML. - 🗂 Include a new Blade partial to enable Markdown-on-paste behavior in rich-text editors. - 📋 Enhance `create` and `edit` forms to normalize descriptions and support Markdown conversion. - 🧪 Add test coverage for Markdown normalization scenarios. - 🛠 Add CLI command to normalize project proposal descriptions in bulk. - 🔧 Update `vite.config.js` for improved development setup (e.g., ignored paths).
102 lines
3.1 KiB
PHP
102 lines
3.1 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Models\ProjectProposal;
|
|
use App\Support\RichTextMarkdownNormalizer;
|
|
use Illuminate\Console\Attributes\Description;
|
|
use Illuminate\Console\Attributes\Signature;
|
|
use Illuminate\Console\Command;
|
|
|
|
#[Signature('project-proposals:normalize-descriptions
|
|
{--dry-run : Show what would change without writing to the database}
|
|
{--id=* : Limit to specific proposal IDs}
|
|
{--show-diff : Print a short before/after preview for every change}')]
|
|
#[Description('Normalize project proposal descriptions so all rows contain clean HTML (converts legacy plain-text and mixed Markdown/HTML content).')]
|
|
class NormalizeProjectProposalDescriptions extends Command
|
|
{
|
|
public function handle(): int
|
|
{
|
|
$dryRun = (bool) $this->option('dry-run');
|
|
$showDiff = (bool) $this->option('show-diff');
|
|
$ids = array_filter((array) $this->option('id'));
|
|
|
|
$normalizer = new RichTextMarkdownNormalizer;
|
|
|
|
$query = ProjectProposal::query()->orderBy('id');
|
|
|
|
if ($ids !== []) {
|
|
$query->whereIn('id', $ids);
|
|
}
|
|
|
|
$total = (clone $query)->count();
|
|
|
|
if ($total === 0) {
|
|
$this->warn('No project proposals to process.');
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
$this->info(sprintf(
|
|
'%s %d project proposal description(s)%s.',
|
|
$dryRun ? 'Analyzing' : 'Normalizing',
|
|
$total,
|
|
$dryRun ? ' (dry-run)' : '',
|
|
));
|
|
|
|
$changed = 0;
|
|
$unchanged = 0;
|
|
$failed = 0;
|
|
|
|
$query->lazy()->each(function (ProjectProposal $proposal) use ($normalizer, $dryRun, $showDiff, &$changed, &$unchanged, &$failed): void {
|
|
$original = (string) ($proposal->description ?? '');
|
|
|
|
try {
|
|
$normalized = (string) ($normalizer->normalize($original) ?? '');
|
|
} catch (\Throwable $exception) {
|
|
$failed++;
|
|
$this->error(sprintf('#%d %s — normalization failed: %s', $proposal->id, $proposal->name, $exception->getMessage()));
|
|
|
|
return;
|
|
}
|
|
|
|
if ($original === $normalized) {
|
|
$unchanged++;
|
|
|
|
return;
|
|
}
|
|
|
|
$changed++;
|
|
$this->line(sprintf('<fg=yellow>~</> #%d %s', $proposal->id, $proposal->name));
|
|
|
|
if ($showDiff) {
|
|
$this->line(' <fg=red>- '.$this->preview($original).'</>');
|
|
$this->line(' <fg=green>+ '.$this->preview($normalized).'</>');
|
|
}
|
|
|
|
if (! $dryRun) {
|
|
$proposal->description = $normalized;
|
|
$proposal->saveQuietly();
|
|
}
|
|
});
|
|
|
|
$this->newLine();
|
|
$this->info(sprintf(
|
|
'Done. Changed: %d, unchanged: %d, failed: %d%s',
|
|
$changed,
|
|
$unchanged,
|
|
$failed,
|
|
$dryRun ? ' (no writes performed)' : '',
|
|
));
|
|
|
|
return $failed > 0 ? self::FAILURE : self::SUCCESS;
|
|
}
|
|
|
|
private function preview(string $value): string
|
|
{
|
|
$collapsed = preg_replace('/\s+/', ' ', trim($value)) ?? '';
|
|
|
|
return mb_strimwidth($collapsed, 0, 140, '…');
|
|
}
|
|
}
|