From 63ea2686e1eb0ca71a5a9c73b218f93ab921dbe3 Mon Sep 17 00:00:00 2001 From: 7IN0SAN9 Date: Mon, 23 Mar 2026 16:30:13 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E7=9F=A5?= =?UTF-8?q?=E8=AF=86=E5=BA=93=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0=E5=92=8C?= =?UTF-8?q?=E5=A4=84=E7=90=86,=20=E6=94=AF=E6=8C=81=20pdf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Filament/Resources/DocumentResource.php | 120 +-- .../DocumentResource/Pages/CreateDocument.php | 23 +- .../DocumentResource/Pages/EditDocument.php | 54 +- .../DocumentResource/Pages/ViewDocument.php | 14 +- app/Jobs/ConvertDocumentToMarkdown.php | 103 +- app/Services/DocumentConversionService.php | 254 +---- app/Services/DocumentPreviewService.php | 265 +---- app/Services/DocumentService.php | 84 -- composer.json | 2 +- composer.lock | 910 ++++++++++-------- config/documents.php | 72 +- package-lock.json | 438 ++++----- .../modals/conversion-error.blade.php | 12 +- .../conversion-error-detail.blade.php | 22 +- .../resources/document/preview.blade.php | 73 +- tests/Feature/DocumentFileNameTest.php | 124 --- tests/Feature/DocumentServiceTest.php | 117 --- 17 files changed, 905 insertions(+), 1782 deletions(-) delete mode 100644 tests/Feature/DocumentFileNameTest.php delete mode 100644 tests/Feature/DocumentServiceTest.php diff --git a/app/Filament/Resources/DocumentResource.php b/app/Filament/Resources/DocumentResource.php index f0f93e2..c0a8c52 100644 --- a/app/Filament/Resources/DocumentResource.php +++ b/app/Filament/Resources/DocumentResource.php @@ -40,13 +40,13 @@ class DocumentResource extends Resource public static function getEloquentQuery(): Builder { $query = parent::getEloquentQuery(); - + // 应用 accessibleBy 作用域,确保用户只能看到有权限的文档 $user = auth()->user(); if ($user) { $query->accessibleBy($user); } - + return $query; } @@ -60,27 +60,32 @@ class DocumentResource extends Resource ->maxLength(255) ->placeholder('请输入文档标题') ->columnSpanFull(), - + Forms\Components\Textarea::make('description') ->label('文档描述') ->rows(3) ->maxLength(65535) ->placeholder('请输入文档描述(可选)') ->columnSpanFull(), - + Forms\Components\FileUpload::make('file') ->label('文档文件') ->required() - ->acceptedFileTypes(['application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document']) + ->acceptedFileTypes(config('documents.supported_formats.mime_types', [ + 'application/msword', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'application/pdf', + 'application/vnd.ms-powerpoint', + 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + ])) ->maxSize(51200) // 50MB ->disk('local') ->directory('documents/' . date('Y/m/d')) ->visibility('private') ->downloadable() - ->preserveFilenames() // 保留原始文件名 - ->helperText('仅支持 .doc 和 .docx 格式,最大 50MB') + ->helperText('支持 .docx/.pptx/.xlsx/.pdf 格式,最大 50MB') ->columnSpanFull(), - + Forms\Components\Select::make('type') ->label('文档类型') ->required() @@ -90,18 +95,19 @@ class DocumentResource extends Resource ]) ->default('global') ->reactive() - ->afterStateUpdated(fn ($state, callable $set) => + ->afterStateUpdated( + fn($state, callable $set) => $state === 'global' ? $set('group_id', null) : null ) ->helperText('全局知识库所有用户可见,专用知识库仅指定分组可见'), - + Forms\Components\Select::make('group_id') ->label('所属分组') ->relationship('group', 'name') ->searchable() ->preload() - ->required(fn (Forms\Get $get): bool => $get('type') === 'dedicated') - ->visible(fn (Forms\Get $get): bool => $get('type') === 'dedicated') + ->required(fn(Forms\Get $get): bool => $get('type') === 'dedicated') + ->visible(fn(Forms\Get $get): bool => $get('type') === 'dedicated') ->helperText('专用知识库必须选择所属分组'), ]); } @@ -122,51 +128,51 @@ class DocumentResource extends Resource } return null; }), - + Tables\Columns\TextColumn::make('type') ->label('文档类型') ->badge() - ->color(fn (string $state): string => match ($state) { + ->color(fn(string $state): string => match ($state) { 'global' => 'success', 'dedicated' => 'warning', }) - ->formatStateUsing(fn (string $state): string => match ($state) { + ->formatStateUsing(fn(string $state): string => match ($state) { 'global' => '全局知识库', 'dedicated' => '专用知识库', default => $state, }) ->sortable(), - + Tables\Columns\TextColumn::make('group.name') ->label('所属分组') ->searchable() ->sortable() ->placeholder('—') ->toggleable(), - + Tables\Columns\TextColumn::make('uploader.name') ->label('上传者') ->searchable() ->sortable() ->toggleable(), - + Tables\Columns\TextColumn::make('file_size') ->label('文件大小') - ->formatStateUsing(fn ($state): string => self::formatFileSize($state)) + ->formatStateUsing(fn($state): string => self::formatFileSize($state)) ->sortable() ->toggleable(), - + Tables\Columns\TextColumn::make('conversion_status') ->label('转换状态') ->badge() - ->color(fn (?string $state): string => match ($state) { + ->color(fn(?string $state): string => match ($state) { 'completed' => 'success', 'processing' => 'info', 'pending' => 'warning', 'failed' => 'danger', default => 'gray', }) - ->formatStateUsing(fn (?string $state): string => match ($state) { + ->formatStateUsing(fn(?string $state): string => match ($state) { 'completed' => '已完成', 'processing' => '转换中', 'pending' => '等待转换', @@ -175,13 +181,13 @@ class DocumentResource extends Resource }) ->sortable() ->toggleable(), - + Tables\Columns\TextColumn::make('created_at') ->label('上传时间') ->dateTime('Y年m月d日 H:i') ->sortable() ->toggleable(), - + Tables\Columns\TextColumn::make('updated_at') ->label('更新时间') ->dateTime('Y年m月d日 H:i') @@ -196,21 +202,21 @@ class DocumentResource extends Resource 'dedicated' => '专用知识库', ]) ->placeholder('全部类型'), - + Tables\Filters\SelectFilter::make('group_id') ->label('所属分组') ->relationship('group', 'name') ->searchable() ->preload() ->placeholder('全部分组'), - + Tables\Filters\SelectFilter::make('uploaded_by') ->label('上传者') ->relationship('uploader', 'name') ->searchable() ->preload() ->placeholder('全部上传者'), - + Tables\Filters\SelectFilter::make('conversion_status') ->label('转换状态') ->options([ @@ -226,32 +232,29 @@ class DocumentResource extends Resource ->label('重试转换') ->icon('heroicon-o-arrow-path') ->color('warning') - ->visible(fn (Document $record): bool => + ->visible( + fn(Document $record): bool => in_array($record->conversion_status, ['failed', 'processing', 'pending']) ) ->requiresConfirmation() ->modalHeading('重试文档转换') - ->modalDescription(fn (Document $record): string => - '确定要重新转换文档 "' . $record->title . '" 吗?' . - "\n\n当前状态:" . match($record->conversion_status) { - 'failed' => '转换失败', - 'processing' => '转换中(可能卡住)', - 'pending' => '等待转换', - default => $record->conversion_status, - } . - ($record->conversion_error ? "\n\n错误信息:" . $record->conversion_error : '') + ->modalDescription( + fn(Document $record): string => + '确定要重新转换文档 "' . $record->title . '" 吗?' . + "\n\n当前状态:" . match ($record->conversion_status) { + 'failed' => '转换失败', + 'processing' => '转换中(可能卡住)', + 'pending' => '等待转换', + default => $record->conversion_status, + } . + ($record->conversion_error ? "\n\n错误信息:" . $record->conversion_error : '') ) ->modalSubmitActionLabel('确认重试') ->action(function (Document $record) { try { - // 重置转换状态 - $record->conversion_status = 'pending'; - $record->conversion_error = null; - $record->save(); - - // 重新派发转换任务 - \App\Jobs\ConvertDocumentToMarkdown::dispatch($record); - + app(\App\Services\DocumentConversionService::class) + ->queueConversion($record); + \Filament\Notifications\Notification::make() ->success() ->title('重试成功') @@ -269,11 +272,13 @@ class DocumentResource extends Resource ->label('查看错误') ->icon('heroicon-o-exclamation-triangle') ->color('danger') - ->visible(fn (Document $record): bool => + ->visible( + fn(Document $record): bool => $record->conversion_status === 'failed' && !empty($record->conversion_error) ) ->modalHeading('转换错误详情') - ->modalContent(fn (Document $record): \Illuminate\Contracts\View\View => + ->modalContent( + fn(Document $record): \Illuminate\Contracts\View\View => view('filament.modals.conversion-error', [ 'document' => $record, 'error' => $record->conversion_error, @@ -285,12 +290,13 @@ class DocumentResource extends Resource ->label('预览 Markdown') ->icon('heroicon-o-eye') ->color('info') - ->visible(fn (Document $record): bool => $record->conversion_status === 'completed') - ->url(fn (Document $record): string => route('documents.preview', $record)) + ->visible(fn(Document $record): bool => $record->conversion_status === 'completed') + ->url(fn(Document $record): string => route('documents.preview', $record)) ->openUrlInNewTab() - ->tooltip(fn (Document $record): ?string => - $record->conversion_status !== 'completed' - ? '文档尚未完成转换' + ->tooltip( + fn(Document $record): ?string => + $record->conversion_status !== 'completed' + ? '文档尚未完成转换' : null ), Tables\Actions\Action::make('download') @@ -300,11 +306,11 @@ class DocumentResource extends Resource ->action(function (Document $record) { $documentService = app(\App\Services\DocumentService::class); $user = auth()->user(); - + try { // 记录下载日志 $documentService->logDownload($record, $user); - + // 返回文件下载响应 return $documentService->downloadDocument($record, $user); } catch (\Exception $e) { @@ -313,7 +319,7 @@ class DocumentResource extends Resource ->title('下载失败') ->body($e->getMessage()) ->send(); - + return null; } }), @@ -341,13 +347,13 @@ class DocumentResource extends Resource if ($bytes === null) { return '—'; } - + $units = ['B', 'KB', 'MB', 'GB']; $bytes = max($bytes, 0); $pow = floor(($bytes ? log($bytes) : 0) / log(1024)); $pow = min($pow, count($units) - 1); $bytes /= (1 << (10 * $pow)); - + return round($bytes, 2) . ' ' . $units[$pow]; } diff --git a/app/Filament/Resources/DocumentResource/Pages/CreateDocument.php b/app/Filament/Resources/DocumentResource/Pages/CreateDocument.php index dccc072..3225506 100644 --- a/app/Filament/Resources/DocumentResource/Pages/CreateDocument.php +++ b/app/Filament/Resources/DocumentResource/Pages/CreateDocument.php @@ -3,8 +3,6 @@ namespace App\Filament\Resources\DocumentResource\Pages; use App\Filament\Resources\DocumentResource; -use App\Services\DocumentService; -use Filament\Actions; use Filament\Notifications\Notification; use Filament\Resources\Pages\CreateRecord; use Illuminate\Support\Facades\Auth; @@ -16,37 +14,28 @@ class CreateDocument extends CreateRecord protected function mutateFormDataBeforeCreate(array $data): array { - // 设置上传者为当前用户 $data['uploaded_by'] = Auth::id(); - - // 如果是全局文档,确保 group_id 为 null + if ($data['type'] === 'global') { $data['group_id'] = null; } - - // 处理文件上传 + if (isset($data['file'])) { $filePath = $data['file']; - - // 获取原始文件名(由于使用了 preserveFilenames(),basename 就是原始文件名) - $originalFileName = basename($filePath); - - // 保存文件信息 + $data['file_path'] = $filePath; - $data['file_name'] = $originalFileName; // 保存原始文件名 + $data['file_name'] = basename($filePath); $data['file_size'] = Storage::disk('local')->size($filePath); $data['mime_type'] = Storage::disk('local')->mimeType($filePath); - - // 移除临时的 file 字段 + unset($data['file']); } - + return $data; } protected function afterCreate(): void { - // 文档创建后,触发转换任务 $conversionService = app(\App\Services\DocumentConversionService::class); $conversionService->queueConversion($this->record); } diff --git a/app/Filament/Resources/DocumentResource/Pages/EditDocument.php b/app/Filament/Resources/DocumentResource/Pages/EditDocument.php index 4956904..f61b76f 100644 --- a/app/Filament/Resources/DocumentResource/Pages/EditDocument.php +++ b/app/Filament/Resources/DocumentResource/Pages/EditDocument.php @@ -6,12 +6,15 @@ use App\Filament\Resources\DocumentResource; use Filament\Actions; use Filament\Notifications\Notification; use Filament\Resources\Pages\EditRecord; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Storage; class EditDocument extends EditRecord { protected static string $resource = DocumentResource::class; + private ?string $previousFilePath = null; + protected function getHeaderActions(): array { return [ @@ -24,60 +27,55 @@ class EditDocument extends EditRecord protected function mutateFormDataBeforeFill(array $data): array { - // 将文件路径设置到 file 字段以便显示 + $this->previousFilePath = $data['file_path'] ?? null; + if (isset($data['file_path'])) { $data['file'] = $data['file_path']; } - + return $data; } protected function mutateFormDataBeforeSave(array $data): array { - // 如果是全局文档,确保 group_id 为 null if ($data['type'] === 'global') { $data['group_id'] = null; } - - // 处理文件更新 - if (isset($data['file']) && $data['file'] !== $this->record->file_path) { - $filePath = $data['file']; - - // 删除旧的 Word 文件 - if ($this->record->file_path && Storage::disk('local')->exists($this->record->file_path)) { - Storage::disk('local')->delete($this->record->file_path); + + $currentFile = $data['file'] ?? null; + + // 检测文件是否变更:与填充时记录的原始路径比较 + if ($currentFile && $currentFile !== $this->previousFilePath) { + // 删除旧文件 + if ($this->previousFilePath && Storage::disk('local')->exists($this->previousFilePath)) { + Storage::disk('local')->delete($this->previousFilePath); } - - // 删除旧的 Markdown 文件 if ($this->record->markdown_path && Storage::disk('markdown')->exists($this->record->markdown_path)) { Storage::disk('markdown')->delete($this->record->markdown_path); } - - // 获取原始文件名(由于使用了 preserveFilenames(),basename 就是原始文件名) - $originalFileName = basename($filePath); - - // 更新文件信息 - $data['file_path'] = $filePath; - $data['file_name'] = $originalFileName; // 保存原始文件名 - $data['file_size'] = Storage::disk('local')->size($filePath); - $data['mime_type'] = Storage::disk('local')->mimeType($filePath); - - // 重置转换状态,准备重新转换 + + $data['file_path'] = $currentFile; + $data['file_name'] = basename($currentFile); + $data['file_size'] = Storage::disk('local')->size($currentFile); + $data['mime_type'] = Storage::disk('local')->mimeType($currentFile); + + // 重置转换状态,触发重新转换 $data['conversion_status'] = 'pending'; $data['markdown_path'] = null; $data['markdown_preview'] = null; $data['conversion_error'] = null; } - - // 移除临时的 file 字段 + unset($data['file']); - + return $data; } protected function afterSave(): void { - // 如果文档的转换状态是 pending,说明文件已更新,需要触发重新转换 + // 刷新模型以获取最新数据库状态 + $this->record->refresh(); + if ($this->record->conversion_status === 'pending') { $conversionService = app(\App\Services\DocumentConversionService::class); $conversionService->queueConversion($this->record); diff --git a/app/Filament/Resources/DocumentResource/Pages/ViewDocument.php b/app/Filament/Resources/DocumentResource/Pages/ViewDocument.php index 5703743..e18f151 100644 --- a/app/Filament/Resources/DocumentResource/Pages/ViewDocument.php +++ b/app/Filament/Resources/DocumentResource/Pages/ViewDocument.php @@ -34,21 +34,15 @@ class ViewDocument extends ViewRecord ->modalSubmitActionLabel('确认重试') ->action(function () { try { - // 重置转换状态 - $this->record->conversion_status = 'pending'; - $this->record->conversion_error = null; - $this->record->save(); - - // 重新派发转换任务 - \App\Jobs\ConvertDocumentToMarkdown::dispatch($this->record); - + app(\App\Services\DocumentConversionService::class) + ->queueConversion($this->record); + Notification::make() ->success() ->title('重试成功') ->body('文档转换任务已重新加入队列,请稍后查看转换结果。') ->send(); - - // 刷新页面数据 + $this->refreshFormData([ 'conversion_status', 'conversion_error', diff --git a/app/Jobs/ConvertDocumentToMarkdown.php b/app/Jobs/ConvertDocumentToMarkdown.php index 9401650..9bad59d 100644 --- a/app/Jobs/ConvertDocumentToMarkdown.php +++ b/app/Jobs/ConvertDocumentToMarkdown.php @@ -18,39 +18,12 @@ class ConvertDocumentToMarkdown implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - /** - * 任务最大尝试次数 - * - * @var int - */ public $tries; - - /** - * 任务超时时间(秒) - * - * @var int - */ public $timeout; - - /** - * 重试延迟(秒) - * - * @var int - */ public $backoff; - /** - * 文档实例 - * - * @var Document - */ protected Document $document; - /** - * 创建新的任务实例 - * - * @param Document $document - */ public function __construct(Document $document) { $this->document = $document; @@ -59,120 +32,60 @@ class ConvertDocumentToMarkdown implements ShouldQueue $this->backoff = config('documents.conversion.retry_delay', 60); } - /** - * 执行任务 - * - * @param DocumentConversionService $conversionService - * @return void - */ public function handle(DocumentConversionService $conversionService): void { try { Log::info('开始转换文档', [ 'document_id' => $this->document->id, 'document_title' => $this->document->title, + 'file_name' => $this->document->file_name, 'attempt' => $this->attempts(), ]); - // 转换文档为 Markdown $result = $conversionService->convertToMarkdown($this->document); - $markdown = $result['markdown']; - $mediaDir = $result['mediaDir'] ?? null; - $tempDir = $result['tempDir']; - $tempDirName = $result['tempDirName']; - try { - // 保存 Markdown 文件和媒体文件 - $markdownPath = $conversionService->saveMarkdownToFile($this->document, $markdown, $mediaDir); + $markdownPath = $conversionService->saveMarkdownToFile( + $this->document, + $result['markdown'] + ); - // 更新文档的 Markdown 信息 - $conversionService->updateDocumentMarkdown($this->document, $markdownPath); - } finally { - // 清理临时目录 - if (isset($tempDirName) && \Storage::disk('local')->exists($tempDirName)) { - \Storage::disk('local')->deleteDirectory($tempDirName); - } - } + $conversionService->updateDocumentMarkdown($this->document, $markdownPath); Log::info('文档转换成功', [ 'document_id' => $this->document->id, 'document_title' => $this->document->title, 'markdown_path' => $markdownPath, ]); - - // 转换成功后,触发索引(如果需要) - // 这将在后续任务中实现 - // $this->document->searchable(); - } catch (\Exception $e) { Log::error('文档转换失败', [ 'document_id' => $this->document->id, 'document_title' => $this->document->title, + 'file_name' => $this->document->file_name, 'attempt' => $this->attempts(), 'error' => $e->getMessage(), - 'trace' => $e->getTraceAsString(), ]); - // 如果已达到最大重试次数,标记为失败 if ($this->attempts() >= $this->tries) { $conversionService->handleConversionFailure($this->document, $e); } - // 重新抛出异常以触发重试 throw $e; } } - /** - * 任务失败时的处理 - * - * @param \Throwable $exception - * @return void - */ public function failed(\Throwable $exception): void { Log::error('文档转换任务最终失败', [ 'document_id' => $this->document->id, 'document_title' => $this->document->title, + 'file_name' => $this->document->file_name, 'error' => $exception->getMessage(), ]); - // 确保文档状态被标记为失败 $conversionService = app(DocumentConversionService::class); $conversionService->handleConversionFailure( $this->document, $exception instanceof \Exception ? $exception : new \Exception($exception->getMessage()) ); } - - /** - * 递归删除目录 - * - * @param string $dir 目录路径 - * @return void - */ - protected function deleteDirectory(string $dir): void - { - if (!file_exists($dir)) { - return; - } - - if (!is_dir($dir)) { - unlink($dir); - return; - } - - $files = array_diff(scandir($dir), ['.', '..']); - foreach ($files as $file) { - $path = $dir . '/' . $file; - if (is_dir($path)) { - $this->deleteDirectory($path); - } else { - unlink($path); - } - } - - rmdir($dir); - } } - diff --git a/app/Services/DocumentConversionService.php b/app/Services/DocumentConversionService.php index f807627..6ab3890 100644 --- a/app/Services/DocumentConversionService.php +++ b/app/Services/DocumentConversionService.php @@ -4,214 +4,52 @@ namespace App\Services; use App\Models\Document; use Illuminate\Support\Facades\Log; -use Illuminate\Support\Facades\Process; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; +use Paperdoc\Support\DocumentManager; /** * 文档转换服务 - * 负责将 Word 文档转换为 Markdown 格式 + * 使用 paperdoc-lib 将文档(DOCX/PPTX/XLSX/PDF)转换为 Markdown */ class DocumentConversionService { - /** - * 转换驱动 - * - * @var string - */ - protected string $driver; - - /** - * Pandoc 可执行文件路径 - * - * @var string - */ - protected string $pandocPath; - - /** - * 转换超时时间(秒) - * - * @var int - */ - protected int $timeout; - - /** - * Markdown 预览长度 - * - * @var int - */ protected int $previewLength; - /** - * 构造函数 - */ public function __construct() { - $this->driver = config('documents.conversion.driver', 'pandoc'); - $this->pandocPath = config('documents.conversion.pandoc_path', 'pandoc'); - $this->timeout = config('documents.conversion.timeout', 300); $this->previewLength = config('documents.markdown.preview_length', 500); } /** - * 将 Word 文档转换为 Markdown - * - * @param Document $document - * @return array 返回 ['markdown' => string, 'mediaDir' => string|null, 'tempDir' => string] - * @throws \Exception + * 将文档转换为 Markdown */ public function convertToMarkdown(Document $document): array { - if ($this->driver === 'pandoc') { - return $this->convertWithPandoc($document); - } - - throw new \Exception("不支持的转换驱动: {$this->driver}"); - } - - /** - * 使用 Pandoc 转换文档 - * - * @param Document $document - * @return array 返回 ['markdown' => string, 'mediaDir' => string|null] - * @throws \Exception - */ - protected function convertWithPandoc(Document $document): array - { - // 获取文档的完整路径 $documentPath = Storage::disk('local')->path($document->file_path); if (!file_exists($documentPath)) { throw new \Exception("文档文件不存在: {$documentPath}"); } - // 使用 Laravel 存储系统创建临时工作目录 - $tempDirName = 'temp/pandoc_' . uniqid(); - - // 确保临时目录存在 - if (!Storage::disk('local')->exists('temp')) { - Storage::disk('local')->makeDirectory('temp'); + $doc = DocumentManager::open($documentPath, ['ocr' => false]); + $markdown = DocumentManager::renderAs($doc, 'md'); + + if (empty(trim($markdown))) { + throw new \Exception('文档转换后内容为空,可能是扫描件或不支持的内容格式'); } - - Storage::disk('local')->makeDirectory($tempDirName); - $tempDir = Storage::disk('local')->path($tempDirName); - - $tempOutputPath = $tempDir . '/output.md'; - try { - // 在临时目录中执行 Pandoc 转换命令 - $result = Process::timeout($this->timeout) - ->path($tempDir) - ->run([ - $this->pandocPath, - $documentPath, - '-f', $this->getInputFormat($document->mime_type), - '-t', 'markdown', - '-o', $tempOutputPath, - '--wrap=none', // 不自动换行 - '--extract-media=.', // 提取媒体文件到当前目录 - ]); - - if (!$result->successful()) { - throw new \Exception("Pandoc 转换失败: {$result->errorOutput()}"); - } - - // 读取转换后的 Markdown 内容 - if (!file_exists($tempOutputPath)) { - throw new \Exception("转换后的 Markdown 文件不存在"); - } - - $markdown = file_get_contents($tempOutputPath); - - if ($markdown === false) { - throw new \Exception("无法读取转换后的 Markdown 文件"); - } - - // 检查是否有提取的媒体文件 - $mediaDir = $tempDir . '/media'; - $hasMedia = is_dir($mediaDir) && count(glob($mediaDir . '/*')) > 0; - - return [ - 'markdown' => $markdown, - 'mediaDir' => $hasMedia ? $mediaDir : null, - 'tempDir' => $tempDir, - 'tempDirName' => $tempDirName, // 添加相对路径名 - ]; - } catch (\Exception $e) { - // 清理临时目录 - Storage::disk('local')->deleteDirectory($tempDirName); - throw $e; - } + return ['markdown' => $markdown]; } /** - * 递归删除目录 - * - * @param string $dir 目录路径 - * @return void + * 将 Markdown 内容保存到存储 */ - protected function deleteDirectory(string $dir): void + public function saveMarkdownToFile(Document $document, string $markdown): string { - if (!file_exists($dir)) { - return; - } - - if (!is_dir($dir)) { - unlink($dir); - return; - } - - $files = array_diff(scandir($dir), ['.', '..']); - foreach ($files as $file) { - $path = $dir . '/' . $file; - if (is_dir($path)) { - $this->deleteDirectory($path); - } else { - unlink($path); - } - } - - rmdir($dir); - } - - /** - * 根据 MIME 类型获取 Pandoc 输入格式 - * - * @param string $mimeType - * @return string - */ - protected function getInputFormat(string $mimeType): string - { - return match ($mimeType) { - 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx', - 'application/msword' => 'doc', - default => 'docx', - }; - } - - /** - * 将 Markdown 内容和媒体文件保存到存储 - * - * @param Document $document - * @param string $markdown - * @param string|null $mediaDir 临时媒体目录路径 - * @return string 返回 Markdown 文件路径 - * @throws \Exception - */ - public function saveMarkdownToFile(Document $document, string $markdown, ?string $mediaDir = null): string - { - // 生成文件路径 $path = $this->generateMarkdownPath($document); - $directory = dirname($path); - // 如果有媒体文件,先保存它们 - if ($mediaDir && is_dir($mediaDir)) { - $this->saveMediaFiles($mediaDir, $directory); - } - - // 保存 Markdown 文件 $saved = Storage::disk('markdown')->put($path, $markdown); - if (!$saved) { throw new \Exception("无法保存 Markdown 文件"); } @@ -219,83 +57,33 @@ class DocumentConversionService return $path; } - /** - * 保存媒体文件到 storage - * 媒体文件保存在文档的 UUID 目录下的 media 子目录中 - * - * @param string $sourceDir 源媒体目录 - * @param string $targetDir 目标目录(相对于 markdown disk,例如:2025/12/04/{uuid}) - * @return void - */ - protected function saveMediaFiles(string $sourceDir, string $targetDir): void - { - $files = glob($sourceDir . '/*'); - - foreach ($files as $file) { - if (is_file($file)) { - $filename = basename($file); - // 保存到文档目录下的 media 子目录 - $targetPath = $targetDir . '/media/' . $filename; - - // 读取文件内容 - $content = file_get_contents($file); - - // 保存到 storage - Storage::disk('markdown')->put($targetPath, $content); - - Log::info('媒体文件已保存', [ - 'filename' => $filename, - 'path' => $targetPath, - ]); - } - } - } - /** * 生成 Markdown 文件路径 - * 使用 UUID 作为目录名,确保每个文档有独立的 media 目录 - * - * @param Document $document - * @return string */ protected function generateMarkdownPath(Document $document): string { $organizeByDate = config('documents.storage.organize_by_date', true); - - // 生成唯一的 UUID 作为文档目录 $uuid = Str::uuid()->toString(); if ($organizeByDate) { - // 按日期组织: YYYY/MM/DD/{uuid}/{uuid}.md $date = $document->created_at ?? now(); $directory = $date->format('Y/m/d') . '/' . $uuid; } else { - // 直接使用 UUID: {uuid}/{uuid}.md $directory = $uuid; } - // 文件名也使用相同的 UUID - $filename = $uuid . '.md'; - - return "{$directory}/{$filename}"; + return "{$directory}/{$uuid}.md"; } /** * 获取 Markdown 内容的预览(前 N 个字符) - * - * @param string $markdown - * @param int|null $length - * @return string */ public function getMarkdownPreview(string $markdown, ?int $length = null): string { $length = $length ?? $this->previewLength; - - // 移除多余的空白字符 $cleaned = preg_replace('/\s+/', ' ', $markdown); $cleaned = trim($cleaned); - // 截取指定长度 if (mb_strlen($cleaned) <= $length) { return $cleaned; } @@ -305,14 +93,9 @@ class DocumentConversionService /** * 更新文档的 Markdown 信息 - * - * @param Document $document - * @param string $markdownPath - * @return void */ public function updateDocumentMarkdown(Document $document, string $markdownPath): void { - // 读取 Markdown 内容以生成预览 $markdown = Storage::disk('markdown')->get($markdownPath); if ($markdown === false) { @@ -325,7 +108,6 @@ class DocumentConversionService $preview = $this->getMarkdownPreview($markdown); } - // 更新文档记录 $document->update([ 'markdown_path' => $markdownPath, 'markdown_preview' => $preview, @@ -336,21 +118,17 @@ class DocumentConversionService /** * 处理转换失败 - * - * @param Document $document - * @param \Exception $exception - * @return void */ public function handleConversionFailure(Document $document, \Exception $exception): void { Log::error('文档转换失败', [ 'document_id' => $document->id, 'document_title' => $document->title, + 'file_name' => $document->file_name, 'error' => $exception->getMessage(), 'trace' => $exception->getTraceAsString(), ]); - // 更新文档状态 $document->update([ 'conversion_status' => 'failed', 'conversion_error' => $exception->getMessage(), @@ -359,21 +137,15 @@ class DocumentConversionService /** * 将转换任务加入队列 - * - * @param Document $document - * @return void */ public function queueConversion(Document $document): void { - // 更新文档状态为处理中 $document->update([ 'conversion_status' => 'processing', 'conversion_error' => null, ]); - // 分发队列任务 $queue = config('documents.conversion.queue', 'documents'); \App\Jobs\ConvertDocumentToMarkdown::dispatch($document)->onQueue($queue); } } - diff --git a/app/Services/DocumentPreviewService.php b/app/Services/DocumentPreviewService.php index 8ea9f4b..191e834 100644 --- a/app/Services/DocumentPreviewService.php +++ b/app/Services/DocumentPreviewService.php @@ -4,33 +4,25 @@ namespace App\Services; use App\Models\Document; use Illuminate\Support\Facades\Storage; -use PhpOffice\PhpWord\IOFactory; -use PhpOffice\PhpWord\Settings; class DocumentPreviewService { /** - * 将文档转换为 HTML 用于预览 - * 在 Filament 后台中,直接从 Word 转换以保证图片正确显示 - * + * 将文档的 Markdown 内容转换为 HTML 用于预览 + * 统一用于 Filament 后台内联预览和独立预览页面 + * * @param Document $document * @return string HTML 内容 * @throws \Exception */ public function convertToHtml(Document $document): string { - try { - // 直接从 Word 转换,以确保图片正确显示 - // Markdown 转换的图片路径问题较复杂,暂时不使用 - return $this->convertWordToHtml($document); - } catch (\Exception $e) { - throw new \Exception('文档预览失败:' . $e->getMessage()); - } + return $this->convertMarkdownToHtml($document); } /** - * 将 Markdown 转换为 HTML(用于专门的 Markdown 预览页面) - * + * 将 Markdown 转换为 HTML + * * @param Document $document * @return string HTML 内容 * @throws \Exception @@ -38,15 +30,15 @@ class DocumentPreviewService public function convertMarkdownToHtml(Document $document): string { $markdownContent = $document->getMarkdownContent(); - + if (empty($markdownContent)) { throw new \Exception('Markdown 内容为空'); } - // 获取 Markdown 文件的目录(例如:2025/12/04) + // 获取 Markdown 文件的目录 $markdownDir = dirname($document->markdown_path); - // 修复图片路径:将 ./media/ 替换为 /markdown/{date}/media/ + // 修复图片路径:将 ./media/ 替换为 /markdown/{dir}/media/ $markdownContent = preg_replace_callback( '/\(\.\/media\/([^)]+)\)/', function ($matches) use ($markdownDir) { @@ -58,250 +50,19 @@ class DocumentPreviewService // 使用 MarkdownRenderService 转换为 HTML $renderService = app(MarkdownRenderService::class); - $htmlContent = $renderService->render($markdownContent); - return $htmlContent; - } - - /** - * 直接从 Word 文档转换为 HTML - * - * @param Document $document - * @return string HTML 内容 - * @throws \Exception - */ - protected function convertWordToHtml(Document $document): string - { - // 检查文件是否存在 - if (!Storage::disk('local')->exists($document->file_path)) { - throw new \Exception('文档文件不存在'); - } - - // 获取文件的完整路径 - $filePath = Storage::disk('local')->path($document->file_path); - - // 确保临时目录存在并设置 PHPWord 的临时目录 - $tempDir = storage_path('app/temp'); - if (!is_dir($tempDir)) { - mkdir($tempDir, 0755, true); - } - Settings::setTempDir($tempDir); - - // 加载 Word 文档 - $phpWord = IOFactory::load($filePath); - - // 提取图片并转换为 base64 - $images = $this->extractImagesFromDocument($phpWord); - - // 创建 HTML Writer - $htmlWriter = IOFactory::createWriter($phpWord, 'HTML'); - - // 使用 Laravel 存储系统创建临时文件 - $tempFileName = 'temp/doc_preview_' . uniqid() . '.html'; - - // 确保临时目录存在 - if (!Storage::disk('local')->exists('temp')) { - Storage::disk('local')->makeDirectory('temp'); - } - - $tempHtmlPath = Storage::disk('local')->path($tempFileName); - $htmlWriter->save($tempHtmlPath); - - // 读取 HTML 内容 - $htmlContent = Storage::disk('local')->get($tempFileName); - - // 删除临时文件 - Storage::disk('local')->delete($tempFileName); - - // 将图片嵌入为 base64 - $htmlContent = $this->embedImagesInHtml($htmlContent, $images); - - // 清理和美化 HTML - $htmlContent = $this->cleanHtml($htmlContent); - - return $htmlContent; - } - - /** - * 从 Word 文档中提取所有图片 - * - * @param \PhpOffice\PhpWord\PhpWord $phpWord - * @return array 图片数组,键为图片索引,值为 base64 编码的图片数据 - */ - protected function extractImagesFromDocument($phpWord): array - { - $images = []; - $imageIndex = 0; - - foreach ($phpWord->getSections() as $section) { - foreach ($section->getElements() as $element) { - // 处理图片元素 - if (method_exists($element, 'getElements')) { - foreach ($element->getElements() as $childElement) { - if ($childElement instanceof \PhpOffice\PhpWord\Element\Image) { - $imageSource = $childElement->getSource(); - if (file_exists($imageSource)) { - $imageData = file_get_contents($imageSource); - $imageType = $childElement->getImageType(); - $mimeType = $this->getImageMimeType($imageType); - $base64 = base64_encode($imageData); - $images[$imageIndex] = "data:{$mimeType};base64,{$base64}"; - $imageIndex++; - } - } - } - } elseif ($element instanceof \PhpOffice\PhpWord\Element\Image) { - $imageSource = $element->getSource(); - if (file_exists($imageSource)) { - $imageData = file_get_contents($imageSource); - $imageType = $element->getImageType(); - $mimeType = $this->getImageMimeType($imageType); - $base64 = base64_encode($imageData); - $images[$imageIndex] = "data:{$mimeType};base64,{$base64}"; - $imageIndex++; - } - } - } - } - - return $images; - } - - /** - * 根据图片类型获取 MIME 类型 - * - * @param string $imageType - * @return string - */ - protected function getImageMimeType(string $imageType): string - { - $mimeTypes = [ - 'jpg' => 'image/jpeg', - 'jpeg' => 'image/jpeg', - 'png' => 'image/png', - 'gif' => 'image/gif', - 'bmp' => 'image/bmp', - 'svg' => 'image/svg+xml', - ]; - - return $mimeTypes[strtolower($imageType)] ?? 'image/jpeg'; - } - - /** - * 将 HTML 中的图片替换为 base64 编码 - * - * @param string $html - * @param array $images - * @return string - */ - protected function embedImagesInHtml(string $html, array $images): string - { - // PHPWord 生成的 HTML 中,图片通常以 的形式存在 - // 我们需要将这些图片路径替换为 base64 数据 - - $imageIndex = 0; - $html = preg_replace_callback( - '/]*?)src=["\']([^"\']+)["\']([^>]*?)>/i', - function ($matches) use ($images, &$imageIndex) { - $beforeSrc = $matches[1]; - $src = $matches[2]; - $afterSrc = $matches[3]; - - // 如果已经是 base64 或 http 链接,不处理 - if (strpos($src, 'data:') === 0 || strpos($src, 'http') === 0) { - return $matches[0]; - } - - // 使用提取的图片数据 - if (isset($images[$imageIndex])) { - $src = $images[$imageIndex]; - $imageIndex++; - } - - return ""; - }, - $html - ); - - return $html; - } - - - - /** - * 清理和美化 HTML 内容 - * - * @param string $html - * @return string - */ - protected function cleanHtml(string $html): string - { - // 提取 body 内容 - if (preg_match('/]*>(.*?)<\/body>/is', $html, $matches)) { - $html = $matches[1]; - } - - // 添加基本样式 - $styledHtml = '
'; - - $styledHtml .= $html; - $styledHtml .= '
'; - - return $styledHtml; + return $renderService->render($markdownContent); } /** * 检查文档是否可以预览 - * + * * @param Document $document * @return bool */ public function canPreview(Document $document): bool { - // 检查文件扩展名 - $extension = strtolower(pathinfo($document->file_name, PATHINFO_EXTENSION)); - - // 目前支持 .doc 和 .docx - return in_array($extension, ['doc', 'docx']); - } - - /** - * 获取文档预览的纯文本内容(用于搜索等) - * - * @param Document $document - * @return string - * @throws \Exception - */ - public function extractText(Document $document): string - { - try { - if (!Storage::disk('local')->exists($document->file_path)) { - throw new \Exception('文档文件不存在'); - } - - $filePath = Storage::disk('local')->path($document->file_path); - $phpWord = IOFactory::load($filePath); - - $text = ''; - foreach ($phpWord->getSections() as $section) { - foreach ($section->getElements() as $element) { - if (method_exists($element, 'getText')) { - $text .= $element->getText() . "\n"; - } - } - } - - return trim($text); - } catch (\Exception $e) { - throw new \Exception('文本提取失败:' . $e->getMessage()); - } + return $document->conversion_status === 'completed' + && !empty($document->markdown_path); } } diff --git a/app/Services/DocumentService.php b/app/Services/DocumentService.php index 33a21ad..dddcfc4 100644 --- a/app/Services/DocumentService.php +++ b/app/Services/DocumentService.php @@ -5,93 +5,22 @@ namespace App\Services; use App\Models\Document; use App\Models\DownloadLog; use App\Models\User; -use Illuminate\Http\UploadedFile; -use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Storage; use Symfony\Component\HttpFoundation\StreamedResponse; class DocumentService { - /** - * 上传文档 - * - * @param UploadedFile $file 上传的文件 - * @param string $title 文档标题 - * @param string $type 文档类型 ('global' 或 'dedicated') - * @param int|null $groupId 分组 ID (专用文档必填) - * @param int $uploaderId 上传者用户 ID - * @return Document - * @throws \Exception - */ - public function uploadDocument( - UploadedFile $file, - string $title, - string $type, - ?int $groupId, - int $uploaderId - ): Document { - // 验证文件格式 - $extension = strtolower($file->getClientOriginalExtension()); - if (!in_array($extension, ['doc', 'docx'])) { - throw new \InvalidArgumentException('文件格式不支持,请上传 Word 文档(.doc 或 .docx)'); - } - - // 验证专用文档必须有分组 - if ($type === 'dedicated' && empty($groupId)) { - throw new \InvalidArgumentException('专用知识库文档必须指定所属分组'); - } - - // 使用事务确保一致性 - return DB::transaction(function () use ($file, $title, $type, $groupId, $uploaderId) { - // 获取原始文件名 - $originalFileName = $file->getClientOriginalName(); - - // 生成文件存储路径,使用原始文件名 - $directory = 'documents/' . date('Y/m/d'); - $filePath = $file->storeAs($directory, $originalFileName, 'local'); - - // 创建数据库记录,设置初始转换状态为 pending - $document = Document::create([ - 'title' => $title, - 'file_path' => $filePath, - 'file_name' => $originalFileName, - 'file_size' => $file->getSize(), - 'mime_type' => $file->getMimeType(), - 'type' => $type, - 'group_id' => $groupId, - 'uploaded_by' => $uploaderId, - 'description' => '', - 'conversion_status' => 'pending', - ]); - - // 文档保存成功后,触发异步转换 - $conversionService = app(DocumentConversionService::class); - $conversionService->queueConversion($document); - - return $document; - }); - } - /** * 验证用户是否有权访问指定文档 - * - * @param Document $document 要访问的文档 - * @param User $user 用户 - * @return bool */ public function validateDocumentAccess(Document $document, User $user): bool { - // 如果是全局文档,所有用户都可以访问 if ($document->type === 'global') { return true; } - // 如果是专用文档,检查用户是否属于该文档的分组 if ($document->type === 'dedicated') { - // 获取用户所属的所有分组 ID $userGroupIds = $user->groups()->pluck('groups.id')->toArray(); - - // 检查文档的分组 ID 是否在用户的分组列表中 return in_array($document->group_id, $userGroupIds); } @@ -100,25 +29,17 @@ class DocumentService /** * 下载文档 - * - * @param Document $document 要下载的文档 - * @param User $user 用户 - * @return StreamedResponse - * @throws \Exception */ public function downloadDocument(Document $document, User $user): StreamedResponse { - // 验证用户权限 if (!$this->validateDocumentAccess($document, $user)) { throw new \Exception('您没有权限访问此文档'); } - // 检查文件是否存在 if (!Storage::disk('local')->exists($document->file_path)) { throw new \Exception('文档不存在或已被删除'); } - // 返回文件流式响应,使用原始文件名 return Storage::disk('local')->download( $document->file_path, $document->file_name @@ -127,11 +48,6 @@ class DocumentService /** * 记录文档下载日志 - * - * @param Document $document 被下载的文档 - * @param User $user 下载的用户 - * @param string|null $ipAddress IP 地址 - * @return DownloadLog */ public function logDownload(Document $document, User $user, ?string $ipAddress = null): DownloadLog { diff --git a/composer.json b/composer.json index e6fa0b4..cafc00e 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "league/commonmark": "^2.8", "maatwebsite/excel": "^3.1", "meilisearch/meilisearch-php": "^1.16", - "phpoffice/phpword": "^1.4", + "paperdoc-dev/paperdoc-lib": "^0.3.5", "solution-forest/filament-tree": "^2.0", "spatie/laravel-activitylog": "^4.12", "spatie/laravel-permission": "^6.24" diff --git a/composer.lock b/composer.lock index 387efe6..4cc3b62 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "316d29450fc96f2d79ed216639e6cfb2", + "content-hash": "7ac0bdce6d17a09797646ea53c4b658a", "packages": [ { "name": "abdelhamiderrahmouni/filament-monaco-editor", @@ -92,29 +92,28 @@ }, { "name": "anourvalar/eloquent-serialize", - "version": "1.3.5", + "version": "1.3.6", "source": { "type": "git", "url": "https://github.com/AnourValar/eloquent-serialize.git", - "reference": "1a7dead8d532657e5358f8f27c0349373517681e" + "reference": "42645e5515d6105c0e6db202f93cab3d36cdce74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/AnourValar/eloquent-serialize/zipball/1a7dead8d532657e5358f8f27c0349373517681e", - "reference": "1a7dead8d532657e5358f8f27c0349373517681e", + "url": "https://api.github.com/repos/AnourValar/eloquent-serialize/zipball/42645e5515d6105c0e6db202f93cab3d36cdce74", + "reference": "42645e5515d6105c0e6db202f93cab3d36cdce74", "shasum": "" }, "require": { - "laravel/framework": "^8.0|^9.0|^10.0|^11.0|^12.0", + "laravel/framework": "^8.0|^9.0|^10.0|^11.0|^12.0|^13.0", "php": "^7.4|^8.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.26", "laravel/legacy-factories": "^1.1", - "orchestra/testbench": "^6.0|^7.0|^8.0|^9.0|^10.0", + "orchestra/testbench": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", "phpstan/phpstan": "^2.0", "phpunit/phpunit": "^9.5|^10.5|^11.0", - "psalm/plugin-laravel": "^2.8|^3.0", "squizlabs/php_codesniffer": "^3.7" }, "type": "library", @@ -152,32 +151,32 @@ ], "support": { "issues": "https://github.com/AnourValar/eloquent-serialize/issues", - "source": "https://github.com/AnourValar/eloquent-serialize/tree/1.3.5" + "source": "https://github.com/AnourValar/eloquent-serialize/tree/1.3.6" }, - "time": "2025-12-04T13:38:21+00:00" + "time": "2026-03-18T15:36:03+00:00" }, { "name": "blade-ui-kit/blade-heroicons", - "version": "2.6.0", + "version": "2.7.0", "source": { "type": "git", "url": "https://github.com/driesvints/blade-heroicons.git", - "reference": "4553b2a1f6c76f0ac7f3bc0de4c0cfa06a097d19" + "reference": "66fa8ba09dba12e0cdb410b8cb94f3b890eca440" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/driesvints/blade-heroicons/zipball/4553b2a1f6c76f0ac7f3bc0de4c0cfa06a097d19", - "reference": "4553b2a1f6c76f0ac7f3bc0de4c0cfa06a097d19", + "url": "https://api.github.com/repos/driesvints/blade-heroicons/zipball/66fa8ba09dba12e0cdb410b8cb94f3b890eca440", + "reference": "66fa8ba09dba12e0cdb410b8cb94f3b890eca440", "shasum": "" }, "require": { "blade-ui-kit/blade-icons": "^1.6", - "illuminate/support": "^9.0|^10.0|^11.0|^12.0", + "illuminate/support": "^9.0|^10.0|^11.0|^12.0|^13.0", "php": "^8.0" }, "require-dev": { - "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", - "phpunit/phpunit": "^9.0|^10.5|^11.0" + "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0|^11.0", + "phpunit/phpunit": "^9.0|^10.5|^11.0|^12.0" }, "type": "library", "extra": { @@ -203,7 +202,7 @@ } ], "description": "A package to easily make use of Heroicons in your Laravel Blade views.", - "homepage": "https://github.com/blade-ui-kit/blade-heroicons", + "homepage": "https://github.com/driesvints/blade-heroicons", "keywords": [ "Heroicons", "blade", @@ -211,7 +210,7 @@ ], "support": { "issues": "https://github.com/driesvints/blade-heroicons/issues", - "source": "https://github.com/driesvints/blade-heroicons/tree/2.6.0" + "source": "https://github.com/driesvints/blade-heroicons/tree/2.7.0" }, "funding": [ { @@ -223,7 +222,7 @@ "type": "paypal" } ], - "time": "2025-02-13T20:53:33+00:00" + "time": "2026-03-16T13:00:23+00:00" }, { "name": "blade-ui-kit/blade-icons", @@ -644,27 +643,27 @@ }, { "name": "danharrin/livewire-rate-limiting", - "version": "v2.1.0", + "version": "v2.2.0", "source": { "type": "git", "url": "https://github.com/danharrin/livewire-rate-limiting.git", - "reference": "14dde653a9ae8f38af07a0ba4921dc046235e1a0" + "reference": "c03e649220089f6e5a52d422e24e3f98c73e456d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/danharrin/livewire-rate-limiting/zipball/14dde653a9ae8f38af07a0ba4921dc046235e1a0", - "reference": "14dde653a9ae8f38af07a0ba4921dc046235e1a0", + "url": "https://api.github.com/repos/danharrin/livewire-rate-limiting/zipball/c03e649220089f6e5a52d422e24e3f98c73e456d", + "reference": "c03e649220089f6e5a52d422e24e3f98c73e456d", "shasum": "" }, "require": { - "illuminate/support": "^9.0|^10.0|^11.0|^12.0", + "illuminate/support": "^9.0|^10.0|^11.0|^12.0|^13.0", "php": "^8.0" }, "require-dev": { "livewire/livewire": "^3.0", "livewire/volt": "^1.3", - "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", - "phpunit/phpunit": "^9.0|^10.0|^11.5.3" + "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0|^11.0", + "phpunit/phpunit": "^9.0|^10.0|^11.5.3|^12.5.12" }, "type": "library", "autoload": { @@ -694,7 +693,7 @@ "type": "github" } ], - "time": "2025-02-21T08:52:11+00:00" + "time": "2026-03-16T11:29:23+00:00" }, { "name": "dflydev/dot-access-data", @@ -773,16 +772,16 @@ }, { "name": "doctrine/dbal", - "version": "4.4.2", + "version": "4.4.3", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "476f7f0fa6ea4aa5364926db7fabdf6049075722" + "reference": "61e730f1658814821a85f2402c945f3883407dec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/476f7f0fa6ea4aa5364926db7fabdf6049075722", - "reference": "476f7f0fa6ea4aa5364926db7fabdf6049075722", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/61e730f1658814821a85f2402c945f3883407dec", + "reference": "61e730f1658814821a85f2402c945f3883407dec", "shasum": "" }, "require": { @@ -859,7 +858,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/4.4.2" + "source": "https://github.com/doctrine/dbal/tree/4.4.3" }, "funding": [ { @@ -875,7 +874,7 @@ "type": "tidelift" } ], - "time": "2026-02-26T12:12:19+00:00" + "time": "2026-03-20T08:52:12+00:00" }, { "name": "doctrine/deprecations", @@ -2383,29 +2382,91 @@ "time": "2025-12-15T11:28:16+00:00" }, { - "name": "kirschbaum-development/eloquent-power-joins", - "version": "4.2.11", + "name": "inspector-apm/inspector-php", + "version": "3.16.15", "source": { "type": "git", - "url": "https://github.com/kirschbaum-development/eloquent-power-joins.git", - "reference": "0e3e3372992e4bf82391b3c7b84b435c3db73588" + "url": "https://github.com/inspector-apm/inspector-php.git", + "reference": "38e76f5f6883745094d641f86a09001a1d7b5eea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kirschbaum-development/eloquent-power-joins/zipball/0e3e3372992e4bf82391b3c7b84b435c3db73588", - "reference": "0e3e3372992e4bf82391b3c7b84b435c3db73588", + "url": "https://api.github.com/repos/inspector-apm/inspector-php/zipball/38e76f5f6883745094d641f86a09001a1d7b5eea", + "reference": "38e76f5f6883745094d641f86a09001a1d7b5eea", "shasum": "" }, "require": { - "illuminate/database": "^11.42|^12.0", - "illuminate/support": "^11.42|^12.0", + "php": "^8.1" + }, + "require-dev": { + "ext-curl": "*", + "friendsofphp/php-cs-fixer": "^3.75", + "neuron-core/neuron-ai": "^2.8", + "phpstan/phpstan": "^2.1", + "phpunit/phpunit": "^9.0", + "rector/rector": "^2.2", + "tomasvotruba/type-coverage": "^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.16.x-dev", + "dev-develop": "3.16.x-dev" + } + }, + "autoload": { + "psr-4": { + "Inspector\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Valerio Barbera", + "email": "valerio@inspector.dev" + } + ], + "description": "Inspector monitoring for PHP applications.", + "keywords": [ + "inspector", + "monitoring", + "observability", + "php", + "telemetry" + ], + "support": { + "issues": "https://github.com/inspector-apm/inspector-php/issues", + "source": "https://github.com/inspector-apm/inspector-php/tree/3.16.15" + }, + "time": "2026-02-26T11:18:52+00:00" + }, + { + "name": "kirschbaum-development/eloquent-power-joins", + "version": "4.3.0", + "source": { + "type": "git", + "url": "https://github.com/kirschbaum-development/eloquent-power-joins.git", + "reference": "dbf2dfaa1900152f2e3dc42b30b67f67a82e7c36" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/kirschbaum-development/eloquent-power-joins/zipball/dbf2dfaa1900152f2e3dc42b30b67f67a82e7c36", + "reference": "dbf2dfaa1900152f2e3dc42b30b67f67a82e7c36", + "shasum": "" + }, + "require": { + "illuminate/database": "^11.42|^12.0|^13.0", + "illuminate/support": "^11.42|^12.0|^13.0", "php": "^8.2" }, "require-dev": { "friendsofphp/php-cs-fixer": "dev-master", - "laravel/legacy-factories": "^1.0@dev", - "orchestra/testbench": "^9.0|^10.0", - "phpunit/phpunit": "^10.0|^11.0" + "laravel/legacy-factories": "^1.0@dev|dev-master", + "orchestra/testbench": "^9.0|^10.0|^11.0", + "phpunit/phpunit": "^10.0|^11.0|^12.0" }, "type": "library", "extra": { @@ -2441,9 +2502,9 @@ ], "support": { "issues": "https://github.com/kirschbaum-development/eloquent-power-joins/issues", - "source": "https://github.com/kirschbaum-development/eloquent-power-joins/tree/4.2.11" + "source": "https://github.com/kirschbaum-development/eloquent-power-joins/tree/4.3.0" }, - "time": "2025-12-17T00:37:48+00:00" + "time": "2026-03-17T16:43:01+00:00" }, { "name": "laminas/laminas-diactoros", @@ -2535,16 +2596,16 @@ }, { "name": "laravel/framework", - "version": "v12.54.1", + "version": "v12.55.1", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "325497463e7599cd14224c422c6e5dd2fe832868" + "reference": "6d9185a248d101b07eecaf8fd60b18129545fd33" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/325497463e7599cd14224c422c6e5dd2fe832868", - "reference": "325497463e7599cd14224c422c6e5dd2fe832868", + "url": "https://api.github.com/repos/laravel/framework/zipball/6d9185a248d101b07eecaf8fd60b18129545fd33", + "reference": "6d9185a248d101b07eecaf8fd60b18129545fd33", "shasum": "" }, "require": { @@ -2660,7 +2721,7 @@ "orchestra/testbench-core": "^10.9.0", "pda/pheanstalk": "^5.0.6|^7.0.0", "php-http/discovery": "^1.15", - "phpstan/phpstan": "^2.0", + "phpstan/phpstan": "^2.1.41", "phpunit/phpunit": "^10.5.35|^11.5.3|^12.0.1", "predis/predis": "^2.3|^3.0", "resend/resend-php": "^0.10.0|^1.0", @@ -2753,31 +2814,31 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2026-03-10T20:25:56+00:00" + "time": "2026-03-18T14:28:59+00:00" }, { "name": "laravel/octane", - "version": "v2.15.0", + "version": "v2.17.1", "source": { "type": "git", "url": "https://github.com/laravel/octane.git", - "reference": "37b6175920bde50584ee4e2fa30ce4ae0f11ae36" + "reference": "eb6150b9aa30956e3a2c04dfebf3a03c5d963a3a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/octane/zipball/37b6175920bde50584ee4e2fa30ce4ae0f11ae36", - "reference": "37b6175920bde50584ee4e2fa30ce4ae0f11ae36", + "url": "https://api.github.com/repos/laravel/octane/zipball/eb6150b9aa30956e3a2c04dfebf3a03c5d963a3a", + "reference": "eb6150b9aa30956e3a2c04dfebf3a03c5d963a3a", "shasum": "" }, "require": { "laminas/laminas-diactoros": "^3.0", - "laravel/framework": "^10.10.1|^11.0|^12.0", + "laravel/framework": "^10.10.1|^11.0|^12.0|^13.0", "laravel/prompts": "^0.1.24|^0.2.0|^0.3.0", "laravel/serializable-closure": "^1.3|^2.0", "nesbot/carbon": "^2.66.0|^3.0", "php": "^8.1.0", - "symfony/console": "^6.0|^7.0", - "symfony/psr-http-message-bridge": "^2.2.0|^6.4|^7.0" + "symfony/console": "^6.0|^7.0|^8.0", + "symfony/psr-http-message-bridge": "^2.2.0|^6.4|^7.0|^8.0" }, "conflict": { "spiral/roadrunner": "<2023.1.0", @@ -2790,11 +2851,10 @@ "laravel/scout": "^10.2.1", "laravel/socialite": "^5.6.1", "livewire/livewire": "^2.12.3|^3.0", - "mockery/mockery": "^1.5.1", "nunomaduro/collision": "^6.4.0|^7.5.2|^8.0", - "orchestra/testbench": "^8.21|^9.0|^10.0", + "orchestra/testbench": "^8.21|^9.0|^10.0|^11.0", "phpstan/phpstan": "^2.1.7", - "phpunit/phpunit": "^10.4|^11.5", + "phpunit/phpunit": "^10.4|^11.5|^12.0|^13.0", "spiral/roadrunner-cli": "^2.6.0", "spiral/roadrunner-http": "^3.3.0" }, @@ -2843,20 +2903,20 @@ "issues": "https://github.com/laravel/octane/issues", "source": "https://github.com/laravel/octane" }, - "time": "2026-03-10T14:27:22+00:00" + "time": "2026-03-18T14:14:24+00:00" }, { "name": "laravel/prompts", - "version": "v0.3.14", + "version": "v0.3.15", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "9f0e371244eedfe2ebeaa72c79c54bb5df6e0176" + "reference": "4bb8107ec97651fd3f17f897d6489dbc4d8fb999" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/9f0e371244eedfe2ebeaa72c79c54bb5df6e0176", - "reference": "9f0e371244eedfe2ebeaa72c79c54bb5df6e0176", + "url": "https://api.github.com/repos/laravel/prompts/zipball/4bb8107ec97651fd3f17f897d6489dbc4d8fb999", + "reference": "4bb8107ec97651fd3f17f897d6489dbc4d8fb999", "shasum": "" }, "require": { @@ -2900,9 +2960,9 @@ "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.3.14" + "source": "https://github.com/laravel/prompts/tree/v0.3.15" }, - "time": "2026-03-01T09:02:38+00:00" + "time": "2026-03-17T13:45:17+00:00" }, { "name": "laravel/scout", @@ -3113,16 +3173,16 @@ }, { "name": "league/commonmark", - "version": "2.8.1", + "version": "2.8.2", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "84b1ca48347efdbe775426f108622a42735a6579" + "reference": "59fb075d2101740c337c7216e3f32b36c204218b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/84b1ca48347efdbe775426f108622a42735a6579", - "reference": "84b1ca48347efdbe775426f108622a42735a6579", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/59fb075d2101740c337c7216e3f32b36c204218b", + "reference": "59fb075d2101740c337c7216e3f32b36c204218b", "shasum": "" }, "require": { @@ -3216,7 +3276,7 @@ "type": "tidelift" } ], - "time": "2026-03-05T21:37:03+00:00" + "time": "2026-03-19T13:16:38+00:00" }, { "name": "league/config", @@ -3581,20 +3641,20 @@ }, { "name": "league/uri", - "version": "7.8.0", + "version": "7.8.1", "source": { "type": "git", "url": "https://github.com/thephpleague/uri.git", - "reference": "4436c6ec8d458e4244448b069cc572d088230b76" + "reference": "08cf38e3924d4f56238125547b5720496fac8fd4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri/zipball/4436c6ec8d458e4244448b069cc572d088230b76", - "reference": "4436c6ec8d458e4244448b069cc572d088230b76", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/08cf38e3924d4f56238125547b5720496fac8fd4", + "reference": "08cf38e3924d4f56238125547b5720496fac8fd4", "shasum": "" }, "require": { - "league/uri-interfaces": "^7.8", + "league/uri-interfaces": "^7.8.1", "php": "^8.1", "psr/http-factory": "^1" }, @@ -3667,7 +3727,7 @@ "docs": "https://uri.thephpleague.com", "forum": "https://thephpleague.slack.com", "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri/tree/7.8.0" + "source": "https://github.com/thephpleague/uri/tree/7.8.1" }, "funding": [ { @@ -3675,20 +3735,20 @@ "type": "github" } ], - "time": "2026-01-14T17:24:56+00:00" + "time": "2026-03-15T20:22:25+00:00" }, { "name": "league/uri-interfaces", - "version": "7.8.0", + "version": "7.8.1", "source": { "type": "git", "url": "https://github.com/thephpleague/uri-interfaces.git", - "reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4" + "reference": "85d5c77c5d6d3af6c54db4a78246364908f3c928" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/c5c5cd056110fc8afaba29fa6b72a43ced42acd4", - "reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/85d5c77c5d6d3af6c54db4a78246364908f3c928", + "reference": "85d5c77c5d6d3af6c54db4a78246364908f3c928", "shasum": "" }, "require": { @@ -3751,7 +3811,7 @@ "docs": "https://uri.thephpleague.com", "forum": "https://thephpleague.slack.com", "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.0" + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.1" }, "funding": [ { @@ -3759,7 +3819,7 @@ "type": "github" } ], - "time": "2026-01-15T06:54:53+00:00" + "time": "2026-03-08T20:05:35+00:00" }, { "name": "livewire/livewire", @@ -3839,29 +3899,29 @@ }, { "name": "maatwebsite/excel", - "version": "3.1.67", + "version": "3.1.68", "source": { "type": "git", "url": "https://github.com/SpartnerNL/Laravel-Excel.git", - "reference": "e508e34a502a3acc3329b464dad257378a7edb4d" + "reference": "1854739267d81d38eae7d8c623caf523f30f256b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/e508e34a502a3acc3329b464dad257378a7edb4d", - "reference": "e508e34a502a3acc3329b464dad257378a7edb4d", + "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/1854739267d81d38eae7d8c623caf523f30f256b", + "reference": "1854739267d81d38eae7d8c623caf523f30f256b", "shasum": "" }, "require": { "composer/semver": "^3.3", "ext-json": "*", - "illuminate/support": "5.8.*||^6.0||^7.0||^8.0||^9.0||^10.0||^11.0||^12.0", + "illuminate/support": "5.8.*||^6.0||^7.0||^8.0||^9.0||^10.0||^11.0||^12.0||^13.0", "php": "^7.0||^8.0", "phpoffice/phpspreadsheet": "^1.30.0", "psr/simple-cache": "^1.0||^2.0||^3.0" }, "require-dev": { - "laravel/scout": "^7.0||^8.0||^9.0||^10.0", - "orchestra/testbench": "^6.0||^7.0||^8.0||^9.0||^10.0", + "laravel/scout": "^7.0||^8.0||^9.0||^10.0||^11.0", + "orchestra/testbench": "^6.0||^7.0||^8.0||^9.0||^10.0||^11.0", "predis/predis": "^1.1" }, "type": "library", @@ -3904,7 +3964,7 @@ ], "support": { "issues": "https://github.com/SpartnerNL/Laravel-Excel/issues", - "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.67" + "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.68" }, "funding": [ { @@ -3916,7 +3976,7 @@ "type": "github" } ], - "time": "2025-08-26T09:13:16+00:00" + "time": "2026-03-17T20:51:10+00:00" }, { "name": "maennchen/zipstream-php", @@ -4616,6 +4676,78 @@ }, "time": "2026-02-13T03:05:33+00:00" }, + { + "name": "neuron-core/neuron-ai", + "version": "3.2.9", + "source": { + "type": "git", + "url": "https://github.com/neuron-core/neuron-ai.git", + "reference": "14585b4658896985be9c125fae10c7d5a1659645" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/neuron-core/neuron-ai/zipball/14585b4658896985be9c125fae10c7d5a1659645", + "reference": "14585b4658896985be9c125fae10c7d5a1659645", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^7.0", + "inspector-apm/inspector-php": "^3.16.12", + "php": "^8.1", + "psr/http-message": "^1.0|^2.0" + }, + "require-dev": { + "amphp/amp": "^3.1.1", + "amphp/http-client": "^5.3", + "aws/aws-sdk-php": "^3.209", + "elasticsearch/elasticsearch": "^8.0", + "ext-pdo": "*", + "friendsofphp/php-cs-fixer": "^3.75", + "google/auth": "^1.49", + "html2text/html2text": "^4.3", + "illuminate/database": "^10.0|^11.0|^12.0", + "laudis/neo4j-php-client": "^3.4", + "opensearch-project/opensearch-php": "^2.5", + "phpstan/phpstan": "^2.1", + "phpunit/phpunit": "^10.0", + "rector/rector": "^2.0", + "spatie/fork": "^1.2", + "tomasvotruba/type-coverage": "^2.0", + "typesense/typesense-php": "^5.0", + "vlucas/phpdotenv": "^5.6" + }, + "bin": [ + "bin/neuron" + ], + "type": "library", + "autoload": { + "psr-4": { + "NeuronAI\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Valerio Barbera", + "email": "valerio@inspector.dev" + } + ], + "description": "The PHP Agentic Framework.", + "support": { + "issues": "https://github.com/neuron-core/neuron-ai/issues", + "source": "https://github.com/neuron-core/neuron-ai/tree/3.2.9" + }, + "funding": [ + { + "url": "https://github.com/neuron-core", + "type": "github" + } + ], + "time": "2026-03-20T17:51:45+00:00" + }, { "name": "nikic/php-parser", "version": "v5.7.0", @@ -4854,6 +4986,85 @@ ], "time": "2025-01-30T13:51:11+00:00" }, + { + "name": "paperdoc-dev/paperdoc-lib", + "version": "v0.3.5", + "source": { + "type": "git", + "url": "https://github.com/paperdoc-dev/paperdoc-lib.git", + "reference": "e164c303a35e75df10dff563f4d33bafe11a3015" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paperdoc-dev/paperdoc-lib/zipball/e164c303a35e75df10dff563f4d33bafe11a3015", + "reference": "e164c303a35e75df10dff563f4d33bafe11a3015", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "ext-zip": "*", + "ext-zlib": "*", + "neuron-core/neuron-ai": "^3.0", + "php": "^8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "illuminate/support": "^11.0|^12.0 Required for Laravel integration (ServiceProvider, Facade)" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Paperdoc": "Paperdoc\\Facades\\Paperdoc" + }, + "providers": [ + "Paperdoc\\PaperdocServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Paperdoc\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "proprietary" + ], + "authors": [ + { + "name": "Paperdoc", + "email": "support@paperdoc.dev" + } + ], + "description": "A zero-dependency PHP library for generating, parsing and converting documents (PDF, HTML, CSV, DOCX)", + "homepage": "https://paperdoc.dev", + "keywords": [ + "converter", + "csv", + "document", + "docx", + "html", + "laravel", + "parser", + "pdf", + "writer" + ], + "support": { + "issues": "https://github.com/paperdoc-dev/paperdoc-lib/issues", + "source": "https://github.com/paperdoc-dev/paperdoc-lib/tree/v0.3.5" + }, + "funding": [ + { + "url": "https://github.com/paperdoc", + "type": "github" + } + ], + "time": "2026-03-04T08:15:03+00:00" + }, { "name": "php-http/discovery", "version": "1.20.0", @@ -4933,58 +5144,6 @@ }, "time": "2024-10-02T11:20:13+00:00" }, - { - "name": "phpoffice/math", - "version": "0.3.0", - "source": { - "type": "git", - "url": "https://github.com/PHPOffice/Math.git", - "reference": "fc31c8f57a7a81f962cbf389fd89f4d9d06fc99a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/Math/zipball/fc31c8f57a7a81f962cbf389fd89f4d9d06fc99a", - "reference": "fc31c8f57a7a81f962cbf389fd89f4d9d06fc99a", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-xml": "*", - "php": "^7.1|^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^0.12.88 || ^1.0.0", - "phpunit/phpunit": "^7.0 || ^9.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "PhpOffice\\Math\\": "src/Math/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Progi1984", - "homepage": "https://lefevre.dev" - } - ], - "description": "Math - Manipulate Math Formula", - "homepage": "https://phpoffice.github.io/Math/", - "keywords": [ - "MathML", - "officemathml", - "php" - ], - "support": { - "issues": "https://github.com/PHPOffice/Math/issues", - "source": "https://github.com/PHPOffice/Math/tree/0.3.0" - }, - "time": "2025-05-29T08:31:49+00:00" - }, { "name": "phpoffice/phpspreadsheet", "version": "1.30.2", @@ -5093,114 +5252,6 @@ }, "time": "2026-01-11T05:58:24+00:00" }, - { - "name": "phpoffice/phpword", - "version": "1.4.0", - "source": { - "type": "git", - "url": "https://github.com/PHPOffice/PHPWord.git", - "reference": "6d75328229bc93790b37e93741adf70646cea958" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/PHPWord/zipball/6d75328229bc93790b37e93741adf70646cea958", - "reference": "6d75328229bc93790b37e93741adf70646cea958", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-gd": "*", - "ext-json": "*", - "ext-xml": "*", - "ext-zip": "*", - "php": "^7.1|^8.0", - "phpoffice/math": "^0.3" - }, - "require-dev": { - "dompdf/dompdf": "^2.0 || ^3.0", - "ext-libxml": "*", - "friendsofphp/php-cs-fixer": "^3.3", - "mpdf/mpdf": "^7.0 || ^8.0", - "phpmd/phpmd": "^2.13", - "phpstan/phpstan": "^0.12.88 || ^1.0.0", - "phpstan/phpstan-phpunit": "^1.0 || ^2.0", - "phpunit/phpunit": ">=7.0", - "symfony/process": "^4.4 || ^5.0", - "tecnickcom/tcpdf": "^6.5" - }, - "suggest": { - "dompdf/dompdf": "Allows writing PDF", - "ext-xmlwriter": "Allows writing OOXML and ODF", - "ext-xsl": "Allows applying XSL style sheet to headers, to main document part, and to footers of an OOXML template" - }, - "type": "library", - "autoload": { - "psr-4": { - "PhpOffice\\PhpWord\\": "src/PhpWord" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0-only" - ], - "authors": [ - { - "name": "Mark Baker" - }, - { - "name": "Gabriel Bull", - "email": "me@gabrielbull.com", - "homepage": "http://gabrielbull.com/" - }, - { - "name": "Franck Lefevre", - "homepage": "https://rootslabs.net/blog/" - }, - { - "name": "Ivan Lanin", - "homepage": "http://ivan.lanin.org" - }, - { - "name": "Roman Syroeshko", - "homepage": "http://ru.linkedin.com/pub/roman-syroeshko/34/a53/994/" - }, - { - "name": "Antoine de Troostembergh" - } - ], - "description": "PHPWord - A pure PHP library for reading and writing word processing documents (OOXML, ODF, RTF, HTML, PDF)", - "homepage": "https://phpoffice.github.io/PHPWord/", - "keywords": [ - "ISO IEC 29500", - "OOXML", - "Office Open XML", - "OpenDocument", - "OpenXML", - "PhpOffice", - "PhpWord", - "Rich Text Format", - "WordprocessingML", - "doc", - "docx", - "html", - "odf", - "odt", - "office", - "pdf", - "php", - "reader", - "rtf", - "template", - "template processor", - "word", - "writer" - ], - "support": { - "issues": "https://github.com/PHPOffice/PHPWord/issues", - "source": "https://github.com/PHPOffice/PHPWord/tree/1.4.0" - }, - "time": "2025-06-05T10:32:36+00:00" - }, { "name": "phpoption/phpoption", "version": "1.9.5", @@ -5739,16 +5790,16 @@ }, { "name": "psy/psysh", - "version": "v0.12.21", + "version": "v0.12.22", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "4821fab5b7cd8c49a673a9fd5754dc9162bb9e97" + "reference": "3be75d5b9244936dd4ac62ade2bfb004d13acf0f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/4821fab5b7cd8c49a673a9fd5754dc9162bb9e97", - "reference": "4821fab5b7cd8c49a673a9fd5754dc9162bb9e97", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/3be75d5b9244936dd4ac62ade2bfb004d13acf0f", + "reference": "3be75d5b9244936dd4ac62ade2bfb004d13acf0f", "shasum": "" }, "require": { @@ -5812,9 +5863,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.12.21" + "source": "https://github.com/bobthecow/psysh/tree/v0.12.22" }, - "time": "2026-03-06T21:21:28+00:00" + "time": "2026-03-22T23:03:24+00:00" }, { "name": "ralouphie/getallheaders", @@ -6016,33 +6067,33 @@ }, { "name": "ryangjchandler/blade-capture-directive", - "version": "v1.1.0", + "version": "v1.1.1", "source": { "type": "git", "url": "https://github.com/ryangjchandler/blade-capture-directive.git", - "reference": "bbb1513dfd89eaec87a47fe0c449a7e3d4a1976d" + "reference": "3f9e80b56ff60b78755ef320e3e16d88850101d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ryangjchandler/blade-capture-directive/zipball/bbb1513dfd89eaec87a47fe0c449a7e3d4a1976d", - "reference": "bbb1513dfd89eaec87a47fe0c449a7e3d4a1976d", + "url": "https://api.github.com/repos/ryangjchandler/blade-capture-directive/zipball/3f9e80b56ff60b78755ef320e3e16d88850101d6", + "reference": "3f9e80b56ff60b78755ef320e3e16d88850101d6", "shasum": "" }, "require": { - "illuminate/contracts": "^10.0|^11.0|^12.0", + "illuminate/contracts": "^10.0|^11.0|^12.0|^13.0", "php": "^8.1", "spatie/laravel-package-tools": "^1.9.2" }, "require-dev": { "nunomaduro/collision": "^7.0|^8.0", "nunomaduro/larastan": "^2.0|^3.0", - "orchestra/testbench": "^8.0|^9.0|^10.0", - "pestphp/pest": "^2.0|^3.7", - "pestphp/pest-plugin-laravel": "^2.0|^3.1", + "orchestra/testbench": "^8.0|^9.0|^10.0|^11.0", + "pestphp/pest": "^2.0|^3.7|^4.1", + "pestphp/pest-plugin-laravel": "^2.0|^3.1|^v4.1.0", "phpstan/extension-installer": "^1.1", "phpstan/phpstan-deprecation-rules": "^1.0|^2.0", "phpstan/phpstan-phpunit": "^1.0|^2.0", - "phpunit/phpunit": "^10.0|^11.5.3", + "phpunit/phpunit": "^10.0|^11.5.3|^12.0", "spatie/laravel-ray": "^1.26" }, "type": "library", @@ -6082,7 +6133,7 @@ ], "support": { "issues": "https://github.com/ryangjchandler/blade-capture-directive/issues", - "source": "https://github.com/ryangjchandler/blade-capture-directive/tree/v1.1.0" + "source": "https://github.com/ryangjchandler/blade-capture-directive/tree/v1.1.1" }, "funding": [ { @@ -6090,7 +6141,7 @@ "type": "github" } ], - "time": "2025-02-25T09:09:36+00:00" + "time": "2026-03-19T10:36:26+00:00" }, { "name": "solution-forest/filament-tree", @@ -6434,30 +6485,31 @@ }, { "name": "spatie/laravel-permission", - "version": "6.24.1", + "version": "6.25.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-permission.git", - "reference": "eefc9d17eba80d023d6bff313f882cb2bcd691a3" + "reference": "d7d4cb0d58616722f1afc90e0484e4825155b9b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-permission/zipball/eefc9d17eba80d023d6bff313f882cb2bcd691a3", - "reference": "eefc9d17eba80d023d6bff313f882cb2bcd691a3", + "url": "https://api.github.com/repos/spatie/laravel-permission/zipball/d7d4cb0d58616722f1afc90e0484e4825155b9b3", + "reference": "d7d4cb0d58616722f1afc90e0484e4825155b9b3", "shasum": "" }, "require": { - "illuminate/auth": "^8.12|^9.0|^10.0|^11.0|^12.0", - "illuminate/container": "^8.12|^9.0|^10.0|^11.0|^12.0", - "illuminate/contracts": "^8.12|^9.0|^10.0|^11.0|^12.0", - "illuminate/database": "^8.12|^9.0|^10.0|^11.0|^12.0", + "illuminate/auth": "^8.12|^9.0|^10.0|^11.0|^12.0|^13.0", + "illuminate/container": "^8.12|^9.0|^10.0|^11.0|^12.0|^13.0", + "illuminate/contracts": "^8.12|^9.0|^10.0|^11.0|^12.0|^13.0", + "illuminate/database": "^8.12|^9.0|^10.0|^11.0|^12.0|^13.0", "php": "^8.0" }, "require-dev": { - "laravel/passport": "^11.0|^12.0", + "laravel/passport": "^11.0|^12.0|^13.0", "laravel/pint": "^1.0", - "orchestra/testbench": "^6.23|^7.0|^8.0|^9.0|^10.0", - "phpunit/phpunit": "^9.4|^10.1|^11.5" + "orchestra/testbench": "^6.23|^7.0|^8.0|^9.0|^10.0|^11.0", + "pestphp/pest": "^2.0|^3.0|^4.0", + "pestphp/pest-plugin-laravel": "^2.0|^3.0|^4.0" }, "type": "library", "extra": { @@ -6505,7 +6557,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-permission/issues", - "source": "https://github.com/spatie/laravel-permission/tree/6.24.1" + "source": "https://github.com/spatie/laravel-permission/tree/6.25.0" }, "funding": [ { @@ -6513,7 +6565,7 @@ "type": "github" } ], - "time": "2026-02-09T21:10:03+00:00" + "time": "2026-03-17T22:46:46+00:00" }, { "name": "symfony/clock", @@ -9760,30 +9812,30 @@ }, { "name": "dragon-code/contracts", - "version": "2.24.0", + "version": "2.25.0", "source": { "type": "git", "url": "https://github.com/TheDragonCode/contracts.git", - "reference": "c21ea4fc0a399bd803a2805a7f2c989749083896" + "reference": "13d1254801026be5ba33cf1309a414953869175f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TheDragonCode/contracts/zipball/c21ea4fc0a399bd803a2805a7f2c989749083896", - "reference": "c21ea4fc0a399bd803a2805a7f2c989749083896", + "url": "https://api.github.com/repos/TheDragonCode/contracts/zipball/13d1254801026be5ba33cf1309a414953869175f", + "reference": "13d1254801026be5ba33cf1309a414953869175f", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", "psr/http-message": "^1.0.1 || ^2.0", - "symfony/http-kernel": "^4.0 || ^5.0 || ^6.0 || ^7.0", + "symfony/http-kernel": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0", "symfony/polyfill-php80": "^1.23" }, "conflict": { "andrey-helldar/contracts": "*" }, "require-dev": { - "illuminate/database": "^10.0 || ^11.0 || ^12.0", - "phpdocumentor/reflection-docblock": "^5.0" + "illuminate/database": "^10.0 || ^11.0 || ^12.0 || ^13.0", + "phpdocumentor/reflection-docblock": "^5.0 || ^6.0" }, "type": "library", "autoload": { @@ -9820,7 +9872,7 @@ "type": "yoomoney" } ], - "time": "2025-02-23T23:11:50+00:00" + "time": "2026-03-17T21:50:20+00:00" }, { "name": "dragon-code/pretty-array", @@ -9893,16 +9945,16 @@ }, { "name": "dragon-code/support", - "version": "6.16.0", + "version": "6.17.0", "source": { "type": "git", "url": "https://github.com/TheDragonCode/support.git", - "reference": "ab9b657a307e75f6ba5b2b39e1e45207dc1a065a" + "reference": "b1e076dc23bed84562af97ee03f8bd840a077706" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TheDragonCode/support/zipball/ab9b657a307e75f6ba5b2b39e1e45207dc1a065a", - "reference": "ab9b657a307e75f6ba5b2b39e1e45207dc1a065a", + "url": "https://api.github.com/repos/TheDragonCode/support/zipball/b1e076dc23bed84562af97ee03f8bd840a077706", + "reference": "b1e076dc23bed84562af97ee03f8bd840a077706", "shasum": "" }, "require": { @@ -9921,7 +9973,7 @@ "andrey-helldar/support": "*" }, "require-dev": { - "illuminate/contracts": "^9.0 || ^10.0 || ^11.0 || ^12.0", + "illuminate/contracts": "^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0", "phpunit/phpunit": "^9.6 || ^11.0 || ^12.0", "symfony/var-dumper": "^6.0 || ^7.0" }, @@ -9984,7 +10036,7 @@ "type": "yoomoney" } ], - "time": "2025-02-24T14:01:52+00:00" + "time": "2026-03-18T20:39:32+00:00" }, { "name": "fidry/cpu-core-counter", @@ -10231,16 +10283,16 @@ }, { "name": "laravel-lang/actions", - "version": "1.12.0", + "version": "1.12.1", "source": { "type": "git", "url": "https://github.com/Laravel-Lang/actions.git", - "reference": "3653188fd43dbb7513a35e58e799324d110bc7d0" + "reference": "af2750ace5fd7655b696c39f3f6d0da9ce852d16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Lang/actions/zipball/3653188fd43dbb7513a35e58e799324d110bc7d0", - "reference": "3653188fd43dbb7513a35e58e799324d110bc7d0", + "url": "https://api.github.com/repos/Laravel-Lang/actions/zipball/af2750ace5fd7655b696c39f3f6d0da9ce852d16", + "reference": "af2750ace5fd7655b696c39f3f6d0da9ce852d16", "shasum": "" }, "require": { @@ -10292,7 +10344,7 @@ ], "support": { "issues": "https://github.com/Laravel-Lang/actions/issues", - "source": "https://github.com/Laravel-Lang/actions/tree/1.12.0" + "source": "https://github.com/Laravel-Lang/actions/tree/1.12.1" }, "funding": [ { @@ -10304,7 +10356,7 @@ "type": "yoomoney" } ], - "time": "2026-01-23T18:52:33+00:00" + "time": "2026-03-17T21:27:37+00:00" }, { "name": "laravel-lang/attributes", @@ -10387,16 +10439,16 @@ }, { "name": "laravel-lang/common", - "version": "6.7.2", + "version": "6.8.0", "source": { "type": "git", "url": "https://github.com/Laravel-Lang/common.git", - "reference": "b2e3089c960106d053b47df3cc66497730130448" + "reference": "f1e3383f94c4f157f0f41324792382bf2dd84d52" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Lang/common/zipball/b2e3089c960106d053b47df3cc66497730130448", - "reference": "b2e3089c960106d053b47df3cc66497730130448", + "url": "https://api.github.com/repos/Laravel-Lang/common/zipball/f1e3383f94c4f157f0f41324792382bf2dd84d52", + "reference": "f1e3383f94c4f157f0f41324792382bf2dd84d52", "shasum": "" }, "require": { @@ -10415,9 +10467,9 @@ }, "require-dev": { "dragon-code/support": "^6.13", - "orchestra/testbench": "^8.17 || ^9.1.2 || ^10.0", + "orchestra/testbench": "^8.17 || ^9.1.2 || ^10.0 || ^11.0", "phpunit/phpunit": "^10.5.20 || ^11.0 || ^12.0", - "symfony/var-dumper": "^6.4 || ^7.1.1" + "symfony/var-dumper": "^6.4 || ^7.1.1 || ^8.0" }, "type": "library", "notification-url": "https://packagist.org/downloads/", @@ -10481,31 +10533,31 @@ "type": "yoomoney" } ], - "time": "2026-01-14T22:00:53+00:00" + "time": "2026-03-17T23:15:14+00:00" }, { "name": "laravel-lang/config", - "version": "1.16.0", + "version": "1.17.0", "source": { "type": "git", "url": "https://github.com/Laravel-Lang/config.git", - "reference": "e7cc52bd5695e017ab996a00ee57d81c3232e6e2" + "reference": "77ad089234aa74961ca30c7e6d13db9a62654c87" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Lang/config/zipball/e7cc52bd5695e017ab996a00ee57d81c3232e6e2", - "reference": "e7cc52bd5695e017ab996a00ee57d81c3232e6e2", + "url": "https://api.github.com/repos/Laravel-Lang/config/zipball/77ad089234aa74961ca30c7e6d13db9a62654c87", + "reference": "77ad089234aa74961ca30c7e6d13db9a62654c87", "shasum": "" }, "require": { "archtechx/enums": "^1.0", - "illuminate/config": "^10.0 || ^11.0 || ^12.0", - "illuminate/support": "^10.0 || ^11.0 || ^12.0", + "illuminate/config": "^10.0 || ^11.0 || ^12.0 || ^13.0", + "illuminate/support": "^10.0 || ^11.0 || ^12.0 || ^13.0", "laravel-lang/locale-list": "^1.6", "php": "^8.1" }, "require-dev": { - "orchestra/testbench": "^8.23 || ^9.1 || ^10.0", + "orchestra/testbench": "^8.23 || ^9.1 || ^10.0 || ^11.0", "pestphp/pest": "^2.34 || ^3.0" }, "type": "library", @@ -10553,9 +10605,9 @@ ], "support": { "issues": "https://github.com/Laravel-Lang/config/issues", - "source": "https://github.com/Laravel-Lang/config/tree/1.16.0" + "source": "https://github.com/Laravel-Lang/config/tree/1.17.0" }, - "time": "2026-01-21T07:36:30+00:00" + "time": "2026-03-17T21:23:36+00:00" }, { "name": "laravel-lang/http-statuses", @@ -10636,25 +10688,25 @@ }, { "name": "laravel-lang/json-fallback", - "version": "2.2.1", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/Laravel-Lang/json-fallback.git", - "reference": "0172de25e6cc3c5b26a7c8b778ff4e37f4d913f4" + "reference": "1b02c798da837c63e2d01f45b45bb49367d5b6a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Lang/json-fallback/zipball/0172de25e6cc3c5b26a7c8b778ff4e37f4d913f4", - "reference": "0172de25e6cc3c5b26a7c8b778ff4e37f4d913f4", + "url": "https://api.github.com/repos/Laravel-Lang/json-fallback/zipball/1b02c798da837c63e2d01f45b45bb49367d5b6a1", + "reference": "1b02c798da837c63e2d01f45b45bb49367d5b6a1", "shasum": "" }, "require": { - "illuminate/support": "^10.0 || ^11.0 || ^12.0", - "illuminate/translation": "^10.0 || ^11.0 || ^12.0", + "illuminate/support": "^10.0 || ^11.0 || ^12.0 || ^13.0", + "illuminate/translation": "^10.0 || ^11.0 || ^12.0 || ^13.0", "php": "^8.1" }, "require-dev": { - "orchestra/testbench": "^8.0 || ^9.0 || ^10.0", + "orchestra/testbench": "^8.0 || ^9.0 || ^10.0 || ^11.0", "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0" }, "type": "library", @@ -10681,22 +10733,32 @@ "description": "Adds support for fallback JSON string translation", "support": { "issues": "https://github.com/Laravel-Lang/json-fallback/issues", - "source": "https://github.com/Laravel-Lang/json-fallback/tree/2.2.1" + "source": "https://github.com/Laravel-Lang/json-fallback/tree/2.3.0" }, - "time": "2025-06-23T09:38:43+00:00" + "funding": [ + { + "url": "https://boosty.to/dragon-code", + "type": "boosty" + }, + { + "url": "https://yoomoney.ru/to/410012608840929", + "type": "yoomoney" + } + ], + "time": "2026-03-17T21:18:08+00:00" }, { "name": "laravel-lang/lang", - "version": "15.28.5", + "version": "15.29.2", "source": { "type": "git", "url": "https://github.com/Laravel-Lang/lang.git", - "reference": "ccc092506de639d8cc86bb0d5d05d66cf91c1ef8" + "reference": "791087e95fc8525c227f292ea6f6d4867f0bb2dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Lang/lang/zipball/ccc092506de639d8cc86bb0d5d05d66cf91c1ef8", - "reference": "ccc092506de639d8cc86bb0d5d05d66cf91c1ef8", + "url": "https://api.github.com/repos/Laravel-Lang/lang/zipball/791087e95fc8525c227f292ea6f6d4867f0bb2dc", + "reference": "791087e95fc8525c227f292ea6f6d4867f0bb2dc", "shasum": "" }, "require": { @@ -10757,7 +10819,7 @@ "type": "yoomoney" } ], - "time": "2026-03-03T07:40:07+00:00" + "time": "2026-03-21T00:27:29+00:00" }, { "name": "laravel-lang/locale-list", @@ -10828,23 +10890,23 @@ }, { "name": "laravel-lang/locales", - "version": "2.10.0", + "version": "2.11.0", "source": { "type": "git", "url": "https://github.com/Laravel-Lang/locales.git", - "reference": "8c1d2383ced70a919b3c2f430589be6c81663087" + "reference": "761aa3cfbc5bbe29eb958c9839e7dd3806193bac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Lang/locales/zipball/8c1d2383ced70a919b3c2f430589be6c81663087", - "reference": "8c1d2383ced70a919b3c2f430589be6c81663087", + "url": "https://api.github.com/repos/Laravel-Lang/locales/zipball/761aa3cfbc5bbe29eb958c9839e7dd3806193bac", + "reference": "761aa3cfbc5bbe29eb958c9839e7dd3806193bac", "shasum": "" }, "require": { "archtechx/enums": "^0.3.2 || ^1.0", "dragon-code/support": "^6.11.3", "ext-json": "*", - "illuminate/collections": "^10.0 || ^11.0 || ^12.0", + "illuminate/collections": "^10.0 || ^11.0 || ^12.0 || ^13.0", "laravel-lang/config": "^1.12", "laravel-lang/locale-list": "^1.5", "laravel-lang/native-country-names": "^1.5", @@ -10853,8 +10915,8 @@ "php": "^8.1" }, "require-dev": { - "orchestra/testbench": "^8.0 || ^9.0 || ^10.0", - "pestphp/pest": "^2.24.1 || ^3.0", + "orchestra/testbench": "^8.0 || ^9.0 || ^10.0 || ^11.0", + "pestphp/pest": "^2.24.1 || ^3.0 || ^4.0", "symfony/var-dumper": "^6.0 || ^7.0" }, "type": "library", @@ -10897,27 +10959,27 @@ "issues": "https://github.com/Laravel-Lang/locales/issues", "source": "https://github.com/Laravel-Lang/locales" }, - "time": "2025-02-24T20:38:10+00:00" + "time": "2026-03-17T22:40:41+00:00" }, { "name": "laravel-lang/models", - "version": "1.6.0", + "version": "1.7.0", "source": { "type": "git", "url": "https://github.com/Laravel-Lang/models.git", - "reference": "972d58cd72034f6484876148f1c0bbbb90b2ebdf" + "reference": "a9aa0205ca019f4459ace26b0432b3b6d1886f66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Lang/models/zipball/972d58cd72034f6484876148f1c0bbbb90b2ebdf", - "reference": "972d58cd72034f6484876148f1c0bbbb90b2ebdf", + "url": "https://api.github.com/repos/Laravel-Lang/models/zipball/a9aa0205ca019f4459ace26b0432b3b6d1886f66", + "reference": "a9aa0205ca019f4459ace26b0432b3b6d1886f66", "shasum": "" }, "require": { "composer/class-map-generator": "^1.3", "dragon-code/support": "^6.13", - "illuminate/database": "^10.0 || ^11.0 || ^12.0", - "illuminate/support": "^10.0 || ^11.0 || ^12.0", + "illuminate/database": "^10.0 || ^11.0 || ^12.0 || ^13.0", + "illuminate/support": "^10.0 || ^11.0 || ^12.0 || ^13.0", "laravel-lang/config": "^1.12", "laravel-lang/locales": "^2.10.0", "laravel/prompts": ">=0.1", @@ -10925,7 +10987,7 @@ }, "require-dev": { "laravel/pint": "^1.20", - "orchestra/testbench": "^8.0 || ^9.0 || ^10.0", + "orchestra/testbench": "^8.0 || ^9.0 || ^10.0 || ^11.0", "pestphp/pest": "^2.34 || ^3.0 || ^4.0", "pestphp/pest-plugin-laravel": "^2.4 || ^3.0 || ^4.0", "symfony/var-dumper": "^6.0 || ^7.0" @@ -10991,7 +11053,7 @@ "type": "yoomoney" } ], - "time": "2026-01-14T22:02:36+00:00" + "time": "2026-03-17T23:00:20+00:00" }, { "name": "laravel-lang/moonshine", @@ -11073,32 +11135,32 @@ }, { "name": "laravel-lang/native-country-names", - "version": "1.7.0", + "version": "1.8.0", "source": { "type": "git", "url": "https://github.com/Laravel-Lang/native-country-names.git", - "reference": "66a82c28c5c820239671035aa019012414d5894f" + "reference": "1d293138e34eb9e914bc4568cdebac2cb0a2eb0e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Lang/native-country-names/zipball/66a82c28c5c820239671035aa019012414d5894f", - "reference": "66a82c28c5c820239671035aa019012414d5894f", + "url": "https://api.github.com/repos/Laravel-Lang/native-country-names/zipball/1d293138e34eb9e914bc4568cdebac2cb0a2eb0e", + "reference": "1d293138e34eb9e914bc4568cdebac2cb0a2eb0e", "shasum": "" }, "require": { "dragon-code/support": "^6.11", "ext-json": "*", - "illuminate/collections": "^10.0 || ^11.0 || ^12.0", + "illuminate/collections": "^10.0 || ^11.0 || ^12.0 || ^13.0", "php": "^8.1" }, "require-dev": { - "illuminate/support": "^10.0 || ^11.0 || ^12.0", + "illuminate/support": "^10.0 || ^11.0 || ^12.0 || ^13.0", "laravel-lang/locale-list": "^1.5", - "pestphp/pest": "^2.24.3 || ^3.0", + "pestphp/pest": "^2.0 || ^3.0 || ^4.0", "punic/punic": "^3.8", - "symfony/console": "^6.3 || ^7.0", - "symfony/process": "^6.3 || ^7.0", - "symfony/var-dumper": "^6.3 || ^7.0", + "symfony/console": "^6.0 || ^7.0 || ^8.0", + "symfony/process": "^6.0 || ^7.0 || ^8.0", + "symfony/var-dumper": "^6.0 || ^7.0 || ^8.0", "vlucas/phpdotenv": "^5.6" }, "type": "library", @@ -11151,36 +11213,36 @@ "type": "yoomoney" } ], - "time": "2026-01-21T17:13:07+00:00" + "time": "2026-03-17T22:01:15+00:00" }, { "name": "laravel-lang/native-currency-names", - "version": "1.8.0", + "version": "1.9.0", "source": { "type": "git", "url": "https://github.com/Laravel-Lang/native-currency-names.git", - "reference": "564f05c2034d76166431704f5d965067dd8c80f0" + "reference": "78beb3c74fc49970b2f948def631512d2a71f3d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Lang/native-currency-names/zipball/564f05c2034d76166431704f5d965067dd8c80f0", - "reference": "564f05c2034d76166431704f5d965067dd8c80f0", + "url": "https://api.github.com/repos/Laravel-Lang/native-currency-names/zipball/78beb3c74fc49970b2f948def631512d2a71f3d9", + "reference": "78beb3c74fc49970b2f948def631512d2a71f3d9", "shasum": "" }, "require": { "dragon-code/support": "^6.11", "ext-json": "*", - "illuminate/collections": "^10.0 || ^11.0 || ^12.0", + "illuminate/collections": "^10.0 || ^11.0 || ^12.0 || ^13.0", "php": "^8.1" }, "require-dev": { - "illuminate/support": "^10.0 || ^11.0 || ^12.0", + "illuminate/support": "^10.0 || ^11.0 || ^12.0 || ^13.0", "laravel-lang/locale-list": "^1.2", - "pestphp/pest": "^2.24.3 || ^3.0", + "pestphp/pest": "^2.0 || ^3.0 || ^4.0", "punic/punic": "^3.8", - "symfony/console": "^6.3 || ^7.0", - "symfony/process": "^6.3 || ^7.0", - "symfony/var-dumper": "^6.3 || ^7.0", + "symfony/console": "^6.0 || ^7.0", + "symfony/process": "^6.0 || ^7.0", + "symfony/var-dumper": "^6.0 || ^7.0", "vlucas/phpdotenv": "^5.6" }, "type": "library", @@ -11230,20 +11292,20 @@ "type": "yoomoney" } ], - "time": "2026-01-21T17:17:17+00:00" + "time": "2026-03-17T22:14:24+00:00" }, { "name": "laravel-lang/native-locale-names", - "version": "2.7.0", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/Laravel-Lang/native-locale-names.git", - "reference": "e1e510e9d2699ed7c41453582e5f9efc74d858b3" + "reference": "c9908827c17a345ae9b0a248380bb223c04ed595" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Lang/native-locale-names/zipball/e1e510e9d2699ed7c41453582e5f9efc74d858b3", - "reference": "e1e510e9d2699ed7c41453582e5f9efc74d858b3", + "url": "https://api.github.com/repos/Laravel-Lang/native-locale-names/zipball/c9908827c17a345ae9b0a248380bb223c04ed595", + "reference": "c9908827c17a345ae9b0a248380bb223c04ed595", "shasum": "" }, "require": { @@ -11252,13 +11314,13 @@ "php": "^8.1" }, "require-dev": { - "illuminate/support": "^10.31 || ^11.0 || ^12.0", + "illuminate/support": "^10.0 || ^11.0 || ^12.0 || ^13.0", "laravel-lang/locale-list": "^1.2", - "pestphp/pest": "^2.24.3 || ^3.0", + "pestphp/pest": "^2.24.3 || ^3.0 || ^4.0", "punic/punic": "^3.8", - "symfony/console": "^6.3 || ^7.0", - "symfony/process": "^6.3 || ^7.0", - "symfony/var-dumper": "^6.3 || ^7.0" + "symfony/console": "^6.0 || ^7.0", + "symfony/process": "^6.0 || ^7.0", + "symfony/var-dumper": "^6.0 || ^7.0" }, "type": "library", "autoload": { @@ -11306,20 +11368,20 @@ "type": "yoomoney" } ], - "time": "2026-01-21T17:15:48+00:00" + "time": "2026-03-17T22:08:00+00:00" }, { "name": "laravel-lang/publisher", - "version": "16.7.1", + "version": "16.8.0", "source": { "type": "git", "url": "https://github.com/Laravel-Lang/publisher.git", - "reference": "b58d236ba3b5bebb4cfc87500b52f620ead4485b" + "reference": "e5d3383f5385c2102f8a0d3dbe488ed86cd0250f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Lang/publisher/zipball/b58d236ba3b5bebb4cfc87500b52f620ead4485b", - "reference": "b58d236ba3b5bebb4cfc87500b52f620ead4485b", + "url": "https://api.github.com/repos/Laravel-Lang/publisher/zipball/e5d3383f5385c2102f8a0d3dbe488ed86cd0250f", + "reference": "e5d3383f5385c2102f8a0d3dbe488ed86cd0250f", "shasum": "" }, "require": { @@ -11327,9 +11389,9 @@ "dragon-code/pretty-array": "^4.1", "dragon-code/support": "^6.11.3", "ext-json": "*", - "illuminate/collections": "^10.0 || ^11.0 || ^12.0", - "illuminate/console": "^10.0 || ^11.0 || ^12.0", - "illuminate/support": "^10.0 || ^11.0 || ^12.0", + "illuminate/collections": "^10.0 || ^11.0 || ^12.0 || ^13.0", + "illuminate/console": "^10.0 || ^11.0 || ^12.0 || ^13.0", + "illuminate/support": "^10.0 || ^11.0 || ^12.0 || ^13.0", "laravel-lang/config": "^1.12", "laravel-lang/locales": "^2.10", "league/commonmark": "^2.4.1", @@ -11343,7 +11405,7 @@ }, "require-dev": { "laravel-lang/json-fallback": "^2.2", - "orchestra/testbench": "^8.14 || ^9.0 || ^10.0", + "orchestra/testbench": "^8.14 || ^9.0 || ^10.0 || ^11.0", "phpunit/phpunit": "^10.4.2 || ^11.0 || ^12.0", "symfony/var-dumper": "^6.3.6 || ^7.0" }, @@ -11414,38 +11476,38 @@ "type": "yoomoney" } ], - "time": "2026-01-14T22:00:51+00:00" + "time": "2026-03-17T22:56:20+00:00" }, { "name": "laravel-lang/routes", - "version": "1.10.1", + "version": "1.11.0", "source": { "type": "git", "url": "https://github.com/Laravel-Lang/routes.git", - "reference": "b2352d04358823bdcffb02986463dea245fac781" + "reference": "29d7f83f2679f51187aa4e761d73bb4e0d133bf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Lang/routes/zipball/b2352d04358823bdcffb02986463dea245fac781", - "reference": "b2352d04358823bdcffb02986463dea245fac781", + "url": "https://api.github.com/repos/Laravel-Lang/routes/zipball/29d7f83f2679f51187aa4e761d73bb4e0d133bf4", + "reference": "29d7f83f2679f51187aa4e761d73bb4e0d133bf4", "shasum": "" }, "require": { "codezero/browser-locale": "^3.4", "dragon-code/support": "^6.13", - "illuminate/config": "^10.0 || ^11.0 || ^12.0", - "illuminate/http": "^10.0 || ^11.0 || ^12.0", - "illuminate/routing": "^10.0 || ^11.0 || ^12.0", - "illuminate/support": "^10.0 || ^11.0 || ^12.0", + "illuminate/config": "^10.0 || ^11.0 || ^12.0 || ^13.0", + "illuminate/http": "^10.0 || ^11.0 || ^12.0 || ^13.0", + "illuminate/routing": "^10.0 || ^11.0 || ^12.0 || ^13.0", + "illuminate/support": "^10.0 || ^11.0 || ^12.0 || ^13.0", "laravel-lang/config": "^1.13", "laravel-lang/locales": "^2.10", "php": "^8.1" }, "require-dev": { - "orchestra/testbench": "^8.23 || ^9.1 || ^10.0", - "pestphp/pest": "^2.34 || ^3.0", - "pestphp/pest-plugin-laravel": "^2.4 || ^3.0", - "symfony/var-dumper": "^6.0 || ^7.0" + "orchestra/testbench": "^8.23 || ^9.1 || ^10.0 || ^11.0", + "pestphp/pest": "^2.34 || ^3.0 || ^4.0", + "pestphp/pest-plugin-laravel": "^2.4 || ^3.0 || ^4.0", + "symfony/var-dumper": "^6.0 || ^7.0 || ^8.0" }, "type": "library", "extra": { @@ -11502,20 +11564,20 @@ "type": "yoomoney" } ], - "time": "2026-01-14T13:37:36+00:00" + "time": "2026-03-17T23:06:16+00:00" }, { "name": "laravel-lang/starter-kits", - "version": "1.9.0", + "version": "1.10.1", "source": { "type": "git", "url": "https://github.com/Laravel-Lang/starter-kits.git", - "reference": "c1f3b36949bb7084013b361e5ab0f3734663d84d" + "reference": "a99d03b85e59e66e8b5e2da8996eefb80a794446" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Lang/starter-kits/zipball/c1f3b36949bb7084013b361e5ab0f3734663d84d", - "reference": "c1f3b36949bb7084013b361e5ab0f3734663d84d", + "url": "https://api.github.com/repos/Laravel-Lang/starter-kits/zipball/a99d03b85e59e66e8b5e2da8996eefb80a794446", + "reference": "a99d03b85e59e66e8b5e2da8996eefb80a794446", "shasum": "" }, "require": { @@ -11567,7 +11629,7 @@ ], "support": { "issues": "https://github.com/Laravel-Lang/starter-kits/issues", - "source": "https://github.com/Laravel-Lang/starter-kits/tree/1.9.0" + "source": "https://github.com/Laravel-Lang/starter-kits/tree/1.10.1" }, "funding": [ { @@ -11579,7 +11641,7 @@ "type": "yoomoney" } ], - "time": "2026-02-28T00:57:54+00:00" + "time": "2026-03-20T08:43:52+00:00" }, { "name": "laravel/pail", @@ -11731,16 +11793,16 @@ }, { "name": "laravel/sail", - "version": "v1.53.0", + "version": "v1.54.0", "source": { "type": "git", "url": "https://github.com/laravel/sail.git", - "reference": "e340eaa2bea9b99192570c48ed837155dbf24fbb" + "reference": "bcc5e06f1a79d806d880a4b027964d2aa5872b07" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sail/zipball/e340eaa2bea9b99192570c48ed837155dbf24fbb", - "reference": "e340eaa2bea9b99192570c48ed837155dbf24fbb", + "url": "https://api.github.com/repos/laravel/sail/zipball/bcc5e06f1a79d806d880a4b027964d2aa5872b07", + "reference": "bcc5e06f1a79d806d880a4b027964d2aa5872b07", "shasum": "" }, "require": { @@ -11790,7 +11852,7 @@ "issues": "https://github.com/laravel/sail/issues", "source": "https://github.com/laravel/sail" }, - "time": "2026-02-06T12:16:02+00:00" + "time": "2026-03-11T14:10:52+00:00" }, { "name": "mockery/mockery", @@ -12528,16 +12590,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "6.0.2", + "version": "6.0.3", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "897b5986ece6b4f9d8413fea345c7d49c757d6bf" + "reference": "7bae67520aa9f5ecc506d646810bd40d9da54582" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/897b5986ece6b4f9d8413fea345c7d49c757d6bf", - "reference": "897b5986ece6b4f9d8413fea345c7d49c757d6bf", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/7bae67520aa9f5ecc506d646810bd40d9da54582", + "reference": "7bae67520aa9f5ecc506d646810bd40d9da54582", "shasum": "" }, "require": { @@ -12587,9 +12649,9 @@ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/6.0.2" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/6.0.3" }, - "time": "2026-03-01T18:43:49+00:00" + "time": "2026-03-18T20:49:53+00:00" }, { "name": "phpdocumentor/type-resolver", diff --git a/config/documents.php b/config/documents.php index 00fdeb9..6159fde 100644 --- a/config/documents.php +++ b/config/documents.php @@ -6,35 +6,16 @@ return [ |-------------------------------------------------------------------------- | 文档转换配置 |-------------------------------------------------------------------------- - | - | 这里配置文档转换相关的设置,包括转换驱动、超时时间和队列配置。 - | */ 'conversion' => [ - /* - | 转换驱动 - | 支持的驱动: 'pandoc', 'phpword' - | 推荐使用 pandoc 以获得更好的转换质量 - */ - 'driver' => env('DOCUMENT_CONVERSION_DRIVER', 'pandoc'), - - /* - | Pandoc 可执行文件路径 - | 如果 pandoc 在系统 PATH 中,可以直接使用 'pandoc' - | 否则需要指定完整路径,如 '/usr/local/bin/pandoc' - */ - 'pandoc_path' => env('PANDOC_PATH', '/opt/homebrew/bin/pandoc'), - /* | 转换超时时间(秒) - | 大文档可能需要更长的转换时间 */ 'timeout' => env('CONVERSION_TIMEOUT', 300), /* | 队列名称 - | 文档转换任务将被分发到此队列 */ 'queue' => env('CONVERSION_QUEUE', 'documents'), @@ -49,37 +30,33 @@ return [ 'retry_delay' => env('CONVERSION_RETRY_DELAY', 60), ], + /* + |-------------------------------------------------------------------------- + | 支持的文件格式 + |-------------------------------------------------------------------------- + */ + + 'supported_formats' => [ + 'extensions' => ['docx', 'pdf', 'pptx', 'xlsx'], + + 'mime_types' => [ + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'application/pdf', + 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + ], + ], + /* |-------------------------------------------------------------------------- | Markdown 配置 |-------------------------------------------------------------------------- - | - | Markdown 渲染和处理相关的配置。 - | */ 'markdown' => [ - /* - | Markdown 渲染器 - | 支持的渲染器: 'commonmark', 'parsedown' - */ 'renderer' => env('MARKDOWN_RENDERER', 'commonmark'), - - /* - | 是否清理 HTML 以防止 XSS 攻击 - */ 'sanitize' => env('MARKDOWN_SANITIZE', true), - - /* - | Markdown 预览长度(字符数) - | 用于在数据库中存储的内容摘要 - */ 'preview_length' => env('MARKDOWN_PREVIEW_LENGTH', 500), - - /* - | Markdown 文件最大大小(字节) - | 超过此大小的文件将分块处理 - */ 'max_file_size' => env('MARKDOWN_MAX_FILE_SIZE', 10485760), // 10MB ], @@ -87,26 +64,11 @@ return [ |-------------------------------------------------------------------------- | 存储配置 |-------------------------------------------------------------------------- - | - | 文档和 Markdown 文件的存储配置。 - | */ 'storage' => [ - /* - | 文档存储磁盘 - */ 'documents_disk' => env('DOCUMENTS_DISK', 'documents'), - - /* - | Markdown 存储磁盘 - */ 'markdown_disk' => env('MARKDOWN_DISK', 'markdown'), - - /* - | 是否按日期组织文件目录 - | 格式: YYYY/MM/DD/ - */ 'organize_by_date' => env('STORAGE_ORGANIZE_BY_DATE', true), ], diff --git a/package-lock.json b/package-lock.json index 21a8fb7..4f57e2c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -507,9 +507,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", - "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.0.tgz", + "integrity": "sha512-WOhNW9K8bR3kf4zLxbfg6Pxu2ybOUbB2AjMDHSQx86LIF4rH4Ft7vmMwNt0loO0eonglSNy4cpD3MKXXKQu0/A==", "cpu": [ "arm" ], @@ -521,9 +521,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", - "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.0.tgz", + "integrity": "sha512-u6JHLll5QKRvjciE78bQXDmqRqNs5M/3GVqZeMwvmjaNODJih/WIrJlFVEihvV0MiYFmd+ZyPr9wxOVbPAG2Iw==", "cpu": [ "arm64" ], @@ -535,9 +535,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", - "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.0.tgz", + "integrity": "sha512-qEF7CsKKzSRc20Ciu2Zw1wRrBz4g56F7r/vRwY430UPp/nt1x21Q/fpJ9N5l47WWvJlkNCPJz3QRVw008fi7yA==", "cpu": [ "arm64" ], @@ -549,9 +549,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", - "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.0.tgz", + "integrity": "sha512-WADYozJ4QCnXCH4wPB+3FuGmDPoFseVCUrANmA5LWwGmC6FL14BWC7pcq+FstOZv3baGX65tZ378uT6WG8ynTw==", "cpu": [ "x64" ], @@ -563,9 +563,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", - "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.0.tgz", + "integrity": "sha512-6b8wGHJlDrGeSE3aH5mGNHBjA0TTkxdoNHik5EkvPHCt351XnigA4pS7Wsj/Eo9Y8RBU6f35cjN9SYmCFBtzxw==", "cpu": [ "arm64" ], @@ -577,9 +577,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", - "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.0.tgz", + "integrity": "sha512-h25Ga0t4jaylMB8M/JKAyrvvfxGRjnPQIR8lnCayyzEjEOx2EJIlIiMbhpWxDRKGKF8jbNH01NnN663dH638mA==", "cpu": [ "x64" ], @@ -591,9 +591,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", - "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.0.tgz", + "integrity": "sha512-RzeBwv0B3qtVBWtcuABtSuCzToo2IEAIQrcyB/b2zMvBWVbjo8bZDjACUpnaafaxhTw2W+imQbP2BD1usasK4g==", "cpu": [ "arm" ], @@ -605,9 +605,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", - "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.0.tgz", + "integrity": "sha512-Sf7zusNI2CIU1HLzuu9Tc5YGAHEZs5Lu7N1ssJG4Tkw6e0MEsN7NdjUDDfGNHy2IU+ENyWT+L2obgWiguWibWQ==", "cpu": [ "arm" ], @@ -619,9 +619,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", - "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.0.tgz", + "integrity": "sha512-DX2x7CMcrJzsE91q7/O02IJQ5/aLkVtYFryqCjduJhUfGKG6yJV8hxaw8pZa93lLEpPTP/ohdN4wFz7yp/ry9A==", "cpu": [ "arm64" ], @@ -633,9 +633,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", - "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.0.tgz", + "integrity": "sha512-09EL+yFVbJZlhcQfShpswwRZ0Rg+z/CsSELFCnPt3iK+iqwGsI4zht3secj5vLEs957QvFFXnzAT0FFPIxSrkQ==", "cpu": [ "arm64" ], @@ -647,9 +647,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", - "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.0.tgz", + "integrity": "sha512-i9IcCMPr3EXm8EQg5jnja0Zyc1iFxJjZWlb4wr7U2Wx/GrddOuEafxRdMPRYVaXjgbhvqalp6np07hN1w9kAKw==", "cpu": [ "loong64" ], @@ -661,9 +661,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", - "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.0.tgz", + "integrity": "sha512-DGzdJK9kyJ+B78MCkWeGnpXJ91tK/iKA6HwHxF4TAlPIY7GXEvMe8hBFRgdrR9Ly4qebR/7gfUs9y2IoaVEyog==", "cpu": [ "loong64" ], @@ -675,9 +675,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", - "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.0.tgz", + "integrity": "sha512-RwpnLsqC8qbS8z1H1AxBA1H6qknR4YpPR9w2XX0vo2Sz10miu57PkNcnHVaZkbqyw/kUWfKMI73jhmfi9BRMUQ==", "cpu": [ "ppc64" ], @@ -689,9 +689,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", - "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.0.tgz", + "integrity": "sha512-Z8pPf54Ly3aqtdWC3G4rFigZgNvd+qJlOE52fmko3KST9SoGfAdSRCwyoyG05q1HrrAblLbk1/PSIV+80/pxLg==", "cpu": [ "ppc64" ], @@ -703,9 +703,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", - "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.0.tgz", + "integrity": "sha512-3a3qQustp3COCGvnP4SvrMHnPQ9d1vzCakQVRTliaz8cIp/wULGjiGpbcqrkv0WrHTEp8bQD/B3HBjzujVWLOA==", "cpu": [ "riscv64" ], @@ -717,9 +717,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", - "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.0.tgz", + "integrity": "sha512-pjZDsVH/1VsghMJ2/kAaxt6dL0psT6ZexQVrijczOf+PeP2BUqTHYejk3l6TlPRydggINOeNRhvpLa0AYpCWSQ==", "cpu": [ "riscv64" ], @@ -731,9 +731,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", - "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.0.tgz", + "integrity": "sha512-3ObQs0BhvPgiUVZrN7gqCSvmFuMWvWvsjG5ayJ3Lraqv+2KhOsp+pUbigqbeWqueGIsnn+09HBw27rJ+gYK4VQ==", "cpu": [ "s390x" ], @@ -745,9 +745,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", - "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.0.tgz", + "integrity": "sha512-EtylprDtQPdS5rXvAayrNDYoJhIz1/vzN2fEubo3yLE7tfAw+948dO0g4M0vkTVFhKojnF+n6C8bDNe+gDRdTg==", "cpu": [ "x64" ], @@ -759,9 +759,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", - "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.0.tgz", + "integrity": "sha512-k09oiRCi/bHU9UVFqD17r3eJR9bn03TyKraCrlz5ULFJGdJGi7VOmm9jl44vOJvRJ6P7WuBi/s2A97LxxHGIdw==", "cpu": [ "x64" ], @@ -773,9 +773,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", - "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.0.tgz", + "integrity": "sha512-1o/0/pIhozoSaDJoDcec+IVLbnRtQmHwPV730+AOD29lHEEo4F5BEUB24H0OBdhbBBDwIOSuf7vgg0Ywxdfiiw==", "cpu": [ "x64" ], @@ -787,9 +787,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", - "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.0.tgz", + "integrity": "sha512-pESDkos/PDzYwtyzB5p/UoNU/8fJo68vcXM9ZW2V0kjYayj1KaaUfi1NmTUTUpMn4UhU4gTuK8gIaFO4UGuMbA==", "cpu": [ "arm64" ], @@ -801,9 +801,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", - "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.0.tgz", + "integrity": "sha512-hj1wFStD7B1YBeYmvY+lWXZ7ey73YGPcViMShYikqKT1GtstIKQAtfUI6yrzPjAy/O7pO0VLXGmUVWXQMaYgTQ==", "cpu": [ "arm64" ], @@ -815,9 +815,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", - "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.0.tgz", + "integrity": "sha512-SyaIPFoxmUPlNDq5EHkTbiKzmSEmq/gOYFI/3HHJ8iS/v1mbugVa7dXUzcJGQfoytp9DJFLhHH4U3/eTy2Bq4w==", "cpu": [ "ia32" ], @@ -829,9 +829,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", - "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.0.tgz", + "integrity": "sha512-RdcryEfzZr+lAr5kRm2ucN9aVlCCa2QNq4hXelZxb8GG0NJSazq44Z3PCCc8wISRuCVnGs0lQJVX5Vp6fKA+IA==", "cpu": [ "x64" ], @@ -843,9 +843,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", - "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.0.tgz", + "integrity": "sha512-PrsWNQ8BuE00O3Xsx3ALh2Df8fAj9+cvvX9AIA6o4KpATR98c9mud4XtDWVvsEuyia5U4tVSTKygawyJkjm60w==", "cpu": [ "x64" ], @@ -857,49 +857,49 @@ ] }, "node_modules/@tailwindcss/node": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.1.tgz", - "integrity": "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.2.tgz", + "integrity": "sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.19.0", "jiti": "^2.6.1", - "lightningcss": "1.31.1", + "lightningcss": "1.32.0", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", - "tailwindcss": "4.2.1" + "tailwindcss": "4.2.2" } }, "node_modules/@tailwindcss/oxide": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.1.tgz", - "integrity": "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.2.tgz", + "integrity": "sha512-qEUA07+E5kehxYp9BVMpq9E8vnJuBHfJEC0vPC5e7iL/hw7HR61aDKoVoKzrG+QKp56vhNZe4qwkRmMC0zDLvg==", "dev": true, "license": "MIT", "engines": { "node": ">= 20" }, "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.2.1", - "@tailwindcss/oxide-darwin-arm64": "4.2.1", - "@tailwindcss/oxide-darwin-x64": "4.2.1", - "@tailwindcss/oxide-freebsd-x64": "4.2.1", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", - "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", - "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", - "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", - "@tailwindcss/oxide-linux-x64-musl": "4.2.1", - "@tailwindcss/oxide-wasm32-wasi": "4.2.1", - "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", - "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" + "@tailwindcss/oxide-android-arm64": "4.2.2", + "@tailwindcss/oxide-darwin-arm64": "4.2.2", + "@tailwindcss/oxide-darwin-x64": "4.2.2", + "@tailwindcss/oxide-freebsd-x64": "4.2.2", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.2", + "@tailwindcss/oxide-linux-arm64-gnu": "4.2.2", + "@tailwindcss/oxide-linux-arm64-musl": "4.2.2", + "@tailwindcss/oxide-linux-x64-gnu": "4.2.2", + "@tailwindcss/oxide-linux-x64-musl": "4.2.2", + "@tailwindcss/oxide-wasm32-wasi": "4.2.2", + "@tailwindcss/oxide-win32-arm64-msvc": "4.2.2", + "@tailwindcss/oxide-win32-x64-msvc": "4.2.2" } }, "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.1.tgz", - "integrity": "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.2.tgz", + "integrity": "sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg==", "cpu": [ "arm64" ], @@ -914,9 +914,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.1.tgz", - "integrity": "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.2.tgz", + "integrity": "sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg==", "cpu": [ "arm64" ], @@ -931,9 +931,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.1.tgz", - "integrity": "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.2.tgz", + "integrity": "sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw==", "cpu": [ "x64" ], @@ -948,9 +948,9 @@ } }, "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.1.tgz", - "integrity": "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.2.tgz", + "integrity": "sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ==", "cpu": [ "x64" ], @@ -965,9 +965,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.1.tgz", - "integrity": "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.2.tgz", + "integrity": "sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ==", "cpu": [ "arm" ], @@ -982,9 +982,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.1.tgz", - "integrity": "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.2.tgz", + "integrity": "sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw==", "cpu": [ "arm64" ], @@ -999,9 +999,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.1.tgz", - "integrity": "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.2.tgz", + "integrity": "sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==", "cpu": [ "arm64" ], @@ -1016,9 +1016,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.1.tgz", - "integrity": "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.2.tgz", + "integrity": "sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg==", "cpu": [ "x64" ], @@ -1033,9 +1033,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.1.tgz", - "integrity": "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.2.tgz", + "integrity": "sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==", "cpu": [ "x64" ], @@ -1050,9 +1050,9 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.1.tgz", - "integrity": "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.2.tgz", + "integrity": "sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==", "bundleDependencies": [ "@napi-rs/wasm-runtime", "@emnapi/core", @@ -1080,9 +1080,9 @@ } }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz", - "integrity": "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.2.tgz", + "integrity": "sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ==", "cpu": [ "arm64" ], @@ -1097,9 +1097,9 @@ } }, "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.1.tgz", - "integrity": "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.2.tgz", + "integrity": "sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA==", "cpu": [ "x64" ], @@ -1114,18 +1114,18 @@ } }, "node_modules/@tailwindcss/vite": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.2.1.tgz", - "integrity": "sha512-TBf2sJjYeb28jD2U/OhwdW0bbOsxkWPwQ7SrqGf9sVcoYwZj7rkXljroBO9wKBut9XnmQLXanuDUeqQK0lGg/w==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.2.2.tgz", + "integrity": "sha512-mEiF5HO1QqCLXoNEfXVA1Tzo+cYsrqV7w9Juj2wdUFyW07JRenqMG225MvPwr3ZD9N1bFQj46X7r33iHxLUW0w==", "dev": true, "license": "MIT", "dependencies": { - "@tailwindcss/node": "4.2.1", - "@tailwindcss/oxide": "4.2.1", - "tailwindcss": "4.2.1" + "@tailwindcss/node": "4.2.2", + "@tailwindcss/oxide": "4.2.2", + "tailwindcss": "4.2.2" }, "peerDependencies": { - "vite": "^5.2.0 || ^6 || ^7" + "vite": "^5.2.0 || ^6 || ^7 || ^8" } }, "node_modules/@types/estree": { @@ -1356,9 +1356,9 @@ "license": "MIT" }, "node_modules/enhanced-resolve": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz", - "integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==", + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.1.tgz", + "integrity": "sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==", "dev": true, "license": "MIT", "dependencies": { @@ -1713,9 +1713,9 @@ } }, "node_modules/lightningcss": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz", - "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", "dev": true, "license": "MPL-2.0", "dependencies": { @@ -1729,23 +1729,23 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "lightningcss-android-arm64": "1.31.1", - "lightningcss-darwin-arm64": "1.31.1", - "lightningcss-darwin-x64": "1.31.1", - "lightningcss-freebsd-x64": "1.31.1", - "lightningcss-linux-arm-gnueabihf": "1.31.1", - "lightningcss-linux-arm64-gnu": "1.31.1", - "lightningcss-linux-arm64-musl": "1.31.1", - "lightningcss-linux-x64-gnu": "1.31.1", - "lightningcss-linux-x64-musl": "1.31.1", - "lightningcss-win32-arm64-msvc": "1.31.1", - "lightningcss-win32-x64-msvc": "1.31.1" + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" } }, "node_modules/lightningcss-android-arm64": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz", - "integrity": "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", "cpu": [ "arm64" ], @@ -1764,9 +1764,9 @@ } }, "node_modules/lightningcss-darwin-arm64": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz", - "integrity": "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", "cpu": [ "arm64" ], @@ -1785,9 +1785,9 @@ } }, "node_modules/lightningcss-darwin-x64": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz", - "integrity": "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", "cpu": [ "x64" ], @@ -1806,9 +1806,9 @@ } }, "node_modules/lightningcss-freebsd-x64": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz", - "integrity": "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", "cpu": [ "x64" ], @@ -1827,9 +1827,9 @@ } }, "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz", - "integrity": "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", "cpu": [ "arm" ], @@ -1848,9 +1848,9 @@ } }, "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz", - "integrity": "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", "cpu": [ "arm64" ], @@ -1869,9 +1869,9 @@ } }, "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz", - "integrity": "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", "cpu": [ "arm64" ], @@ -1890,9 +1890,9 @@ } }, "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz", - "integrity": "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", "cpu": [ "x64" ], @@ -1911,9 +1911,9 @@ } }, "node_modules/lightningcss-linux-x64-musl": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz", - "integrity": "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", "cpu": [ "x64" ], @@ -1932,9 +1932,9 @@ } }, "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz", - "integrity": "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", "cpu": [ "arm64" ], @@ -1953,9 +1953,9 @@ } }, "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz", - "integrity": "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", "cpu": [ "x64" ], @@ -2116,9 +2116,9 @@ } }, "node_modules/rollup": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", - "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.0.tgz", + "integrity": "sha512-yqjxruMGBQJ2gG4HtjZtAfXArHomazDHoFwFFmZZl0r7Pdo7qCIXKqKHZc8yeoMgzJJ+pO6pEEHa+V7uzWlrAQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2132,31 +2132,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.59.0", - "@rollup/rollup-android-arm64": "4.59.0", - "@rollup/rollup-darwin-arm64": "4.59.0", - "@rollup/rollup-darwin-x64": "4.59.0", - "@rollup/rollup-freebsd-arm64": "4.59.0", - "@rollup/rollup-freebsd-x64": "4.59.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", - "@rollup/rollup-linux-arm-musleabihf": "4.59.0", - "@rollup/rollup-linux-arm64-gnu": "4.59.0", - "@rollup/rollup-linux-arm64-musl": "4.59.0", - "@rollup/rollup-linux-loong64-gnu": "4.59.0", - "@rollup/rollup-linux-loong64-musl": "4.59.0", - "@rollup/rollup-linux-ppc64-gnu": "4.59.0", - "@rollup/rollup-linux-ppc64-musl": "4.59.0", - "@rollup/rollup-linux-riscv64-gnu": "4.59.0", - "@rollup/rollup-linux-riscv64-musl": "4.59.0", - "@rollup/rollup-linux-s390x-gnu": "4.59.0", - "@rollup/rollup-linux-x64-gnu": "4.59.0", - "@rollup/rollup-linux-x64-musl": "4.59.0", - "@rollup/rollup-openbsd-x64": "4.59.0", - "@rollup/rollup-openharmony-arm64": "4.59.0", - "@rollup/rollup-win32-arm64-msvc": "4.59.0", - "@rollup/rollup-win32-ia32-msvc": "4.59.0", - "@rollup/rollup-win32-x64-gnu": "4.59.0", - "@rollup/rollup-win32-x64-msvc": "4.59.0", + "@rollup/rollup-android-arm-eabi": "4.60.0", + "@rollup/rollup-android-arm64": "4.60.0", + "@rollup/rollup-darwin-arm64": "4.60.0", + "@rollup/rollup-darwin-x64": "4.60.0", + "@rollup/rollup-freebsd-arm64": "4.60.0", + "@rollup/rollup-freebsd-x64": "4.60.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.0", + "@rollup/rollup-linux-arm-musleabihf": "4.60.0", + "@rollup/rollup-linux-arm64-gnu": "4.60.0", + "@rollup/rollup-linux-arm64-musl": "4.60.0", + "@rollup/rollup-linux-loong64-gnu": "4.60.0", + "@rollup/rollup-linux-loong64-musl": "4.60.0", + "@rollup/rollup-linux-ppc64-gnu": "4.60.0", + "@rollup/rollup-linux-ppc64-musl": "4.60.0", + "@rollup/rollup-linux-riscv64-gnu": "4.60.0", + "@rollup/rollup-linux-riscv64-musl": "4.60.0", + "@rollup/rollup-linux-s390x-gnu": "4.60.0", + "@rollup/rollup-linux-x64-gnu": "4.60.0", + "@rollup/rollup-linux-x64-musl": "4.60.0", + "@rollup/rollup-openbsd-x64": "4.60.0", + "@rollup/rollup-openharmony-arm64": "4.60.0", + "@rollup/rollup-win32-arm64-msvc": "4.60.0", + "@rollup/rollup-win32-ia32-msvc": "4.60.0", + "@rollup/rollup-win32-x64-gnu": "4.60.0", + "@rollup/rollup-win32-x64-msvc": "4.60.0", "fsevents": "~2.3.2" } }, @@ -2238,9 +2238,9 @@ } }, "node_modules/tailwindcss": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.1.tgz", - "integrity": "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.2.tgz", + "integrity": "sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==", "dev": true, "license": "MIT" }, diff --git a/resources/views/filament/modals/conversion-error.blade.php b/resources/views/filament/modals/conversion-error.blade.php index 2c9f4f7..67435c1 100644 --- a/resources/views/filament/modals/conversion-error.blade.php +++ b/resources/views/filament/modals/conversion-error.blade.php @@ -10,7 +10,7 @@

文档转换失败

-
+

文档:{{ $document->title }}

文件名:{{ $document->file_name }}

失败时间:{{ $document->updated_at->format('Y年m月d日 H:i:s') }}

@@ -35,14 +35,14 @@

- 常见问题及解决方案 + 常见原因

    -
  • 如果错误提示无法连接到 Meilisearch,请确保搜索服务正常运行
  • -
  • 如果错误提示文件损坏或格式不支持,请检查原始文档是否完整
  • -
  • 如果错误提示超时,可能是文档过大或包含大量图片,请尝试优化文档
  • -
  • 您可以点击"重试转换"按钮重新尝试转换此文档
  • +
  • 文件损坏或格式异常
  • +
  • PDF 扫描件或纯图片文档无法提取文本内容
  • +
  • 文档过大或图片过多,请优化后重新上传
  • +
  • 您可以点击 "重试转换" 按钮重新尝试
diff --git a/resources/views/filament/resources/document/conversion-error-detail.blade.php b/resources/views/filament/resources/document/conversion-error-detail.blade.php index 7157a0c..e6adfa8 100644 --- a/resources/views/filament/resources/document/conversion-error-detail.blade.php +++ b/resources/views/filament/resources/document/conversion-error-detail.blade.php @@ -10,15 +10,17 @@

文档转换失败

-
-

失败时间:{{ $document->updated_at->format('Y年m月d日 H:i:s') }}

+
+

文档:{{ $document->title }}

+

文件名:{{ $document->file_name }}

+

失败时间:{{ $document->updated_at->format('Y年m月d日 H:i:s') }}

-

错误详情:

+

错误信息:

{{ $document->conversion_error }}
@@ -33,25 +35,21 @@

- 常见问题及解决方案 + 常见原因

  • - 无法连接到 Meilisearch:请确保搜索服务正常运行,可以联系系统管理员检查服务状态 + 文件损坏或格式异常:请确认原始文档可以正常打开。
  • - 文件损坏或格式不支持:请检查原始文档是否完整,确保文件格式为 .doc 或 .docx + 转换超时:文档过大或包含大量图片,请尝试拆分或优化后重新上传
  • - 转换超时:可能是文档过大或包含大量图片,建议优化文档后重新上传 -
  • -
  • - - Pandoc 错误:文档可能包含不支持的格式或特殊内容,请尝试简化文档格式 + 内容为空:PDF 扫描件或纯图片文档无法提取文本内容
@@ -71,7 +69,7 @@ 下一步操作
-

您可以点击页面右上角的 "重试转换" 按钮重新尝试转换此文档。如果问题持续存在,请联系系统管理员或尝试重新上传文档。

+

您可以点击页面右上角的 "重试转换" 按钮重新尝试。如果问题持续存在,请联系系统管理员或尝试重新上传文档。

diff --git a/resources/views/filament/resources/document/preview.blade.php b/resources/views/filament/resources/document/preview.blade.php index 19825aa..856ef07 100644 --- a/resources/views/filament/resources/document/preview.blade.php +++ b/resources/views/filament/resources/document/preview.blade.php @@ -1,11 +1,11 @@ @php use App\Services\DocumentPreviewService; - + $previewService = app(DocumentPreviewService::class); $canPreview = $previewService->canPreview($document); $htmlContent = null; $error = null; - + if ($canPreview) { try { $htmlContent = $previewService->convertToHtml($document); @@ -16,30 +16,39 @@ @endphp
- @if ($error) + @if ($document->conversion_status === 'failed') + {{-- 转换失败状态由"转换错误信息"区块处理,此处不重复展示 --}} + @elseif ($document->conversion_status === 'processing') +
+
+ + + + +

文档正在转换中,请稍后刷新页面查看...

+
+
+ @elseif ($document->conversion_status === 'pending') +
+
+ + + +

文档等待转换中...

+
+
+ @elseif ($error)
-

预览失败

+

预览加载失败

{{ $error }}

- @elseif (!$canPreview) -
-
- - - -
-

无法预览此文档

-

该文档格式不支持在线预览,请下载后查看。

-
-
-
@elseif ($htmlContent)
@@ -52,64 +61,48 @@
- +
{!! $htmlContent !!}
- -
-

- 提示:这是文档的预览版本,可能与原始格式略有差异。如需查看完整格式,请下载文档。 -

-
-
- @else -
-
- - - - -

正在加载文档预览...

-
@endif