diff --git a/README.md b/README.md
index 78a7fe5..0173359 100644
--- a/README.md
+++ b/README.md
@@ -175,3 +175,8 @@ php artisan test --compact
## License
MIT
+
+## Documentation Notes
+
+- Documentation screenshots are generated for all admin and user pages.
+- cPanel Migration tabs (Domains, Databases, Mailboxes, Forwarders, SSL) only render after a backup is analyzed. Provide a sample cPanel backup to capture those tab screenshots.
diff --git a/VERSION b/VERSION
index a87052a..3cf2e50 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-VERSION=0.9-rc53
+VERSION=0.9-rc54
diff --git a/app/BackupSchedule.php b/app/BackupSchedule.php
new file mode 100644
index 0000000..0dbafb9
--- /dev/null
+++ b/app/BackupSchedule.php
@@ -0,0 +1,235 @@
+ 'boolean',
+ 'is_server_backup' => 'boolean',
+ 'include_files' => 'boolean',
+ 'include_databases' => 'boolean',
+ 'include_mailboxes' => 'boolean',
+ 'include_dns' => 'boolean',
+ 'domains' => 'array',
+ 'databases' => 'array',
+ 'mailboxes' => 'array',
+ 'users' => 'array',
+ 'metadata' => 'array',
+ 'retention_count' => 'integer',
+ 'day_of_week' => 'integer',
+ 'day_of_month' => 'integer',
+ 'last_run_at' => 'datetime',
+ 'next_run_at' => 'datetime',
+ ];
+ }
+
+ public function user(): BelongsTo
+ {
+ return $this->belongsTo(User::class);
+ }
+
+ public function destination(): BelongsTo
+ {
+ return $this->belongsTo(BackupDestination::class, 'destination_id');
+ }
+
+ public function backups(): HasMany
+ {
+ return $this->hasMany(Backup::class, 'schedule_id');
+ }
+
+ /**
+ * Check if the schedule should run now.
+ */
+ public function shouldRun(): bool
+ {
+ if (! $this->is_active) {
+ return false;
+ }
+
+ if (! $this->next_run_at) {
+ return true;
+ }
+
+ return $this->next_run_at->isPast();
+ }
+
+ /**
+ * Calculate and set the next run time.
+ */
+ public function calculateNextRun(): Carbon
+ {
+ $timezone = $this->getSystemTimezone();
+ $now = Carbon::now($timezone);
+ $time = explode(':', $this->time);
+ $hour = (int) ($time[0] ?? 2);
+ $minute = (int) ($time[1] ?? 0);
+
+ $next = $now->copy()->setTime($hour, $minute, 0);
+
+ // If time already passed today, start from tomorrow
+ if ($next->isPast()) {
+ $next->addDay();
+ }
+
+ switch ($this->frequency) {
+ case 'hourly':
+ $next = $now->copy()->addHour()->startOfHour();
+ break;
+
+ case 'daily':
+ // Already set to next occurrence
+ break;
+
+ case 'weekly':
+ $targetDay = $this->day_of_week ?? 0; // Default to Sunday
+ while ($next->dayOfWeek !== $targetDay) {
+ $next->addDay();
+ }
+ break;
+
+ case 'monthly':
+ $targetDay = $this->day_of_month ?? 1;
+ $next->day = min($targetDay, $next->daysInMonth);
+ if ($next->isPast()) {
+ $next->addMonth();
+ $next->day = min($targetDay, $next->daysInMonth);
+ }
+ break;
+ }
+
+ $nextUtc = $next->copy()->setTimezone('UTC');
+ $this->attributes['next_run_at'] = $nextUtc->format($this->getDateFormat());
+
+ return $nextUtc;
+ }
+
+ /**
+ * Get frequency label for UI.
+ */
+ public function getFrequencyLabelAttribute(): string
+ {
+ $base = match ($this->frequency) {
+ 'hourly' => 'Every hour',
+ 'daily' => 'Daily at '.$this->time,
+ 'weekly' => 'Weekly on '.$this->getDayName().' at '.$this->time,
+ 'monthly' => 'Monthly on day '.($this->day_of_month ?? 1).' at '.$this->time,
+ default => ucfirst($this->frequency),
+ };
+
+ return $base;
+ }
+
+ /**
+ * Get day name for weekly schedules.
+ */
+ protected function getDayName(): string
+ {
+ $days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
+
+ return $days[$this->day_of_week ?? 0];
+ }
+
+ protected function getSystemTimezone(): string
+ {
+ static $timezone = null;
+ if ($timezone === null) {
+ $timezone = trim((string) @file_get_contents('/etc/timezone'));
+ if ($timezone === '') {
+ $timezone = trim((string) @shell_exec('timedatectl show -p Timezone --value 2>/dev/null'));
+ }
+ if ($timezone === '') {
+ $timezone = 'UTC';
+ }
+ }
+
+ return $timezone;
+ }
+
+ /**
+ * Scope for active schedules.
+ */
+ public function scopeActive($query)
+ {
+ return $query->where('is_active', true);
+ }
+
+ /**
+ * Scope for due schedules.
+ */
+ public function scopeDue($query)
+ {
+ return $query->active()
+ ->where(function ($q) {
+ $q->whereNull('next_run_at')
+ ->orWhere('next_run_at', '<=', now());
+ });
+ }
+
+ /**
+ * Scope for user schedules.
+ */
+ public function scopeForUser($query, int $userId)
+ {
+ return $query->where('user_id', $userId);
+ }
+
+ /**
+ * Scope for server backup schedules.
+ */
+ public function scopeServerBackups($query)
+ {
+ return $query->where('is_server_backup', true);
+ }
+
+ /**
+ * Get last status color for UI.
+ */
+ public function getLastStatusColorAttribute(): string
+ {
+ return match ($this->last_status) {
+ 'success' => 'success',
+ 'failed' => 'danger',
+ default => 'gray',
+ };
+ }
+}
diff --git a/app/Backups.php b/app/Backups.php
new file mode 100644
index 0000000..a77c36f
--- /dev/null
+++ b/app/Backups.php
@@ -0,0 +1,1616 @@
+activeTab = $this->normalizeTabName($this->activeTab);
+ }
+
+ protected function normalizeTabName(?string $tab): string
+ {
+ return match ($tab) {
+ 'destinations', 'schedules', 'backups' => $tab,
+ default => 'destinations',
+ };
+ }
+
+ public function setTab(string $tab): void
+ {
+ $this->activeTab = $this->normalizeTabName($tab);
+ $this->resetTable();
+ }
+
+ public function updatedActiveTab(): void
+ {
+ $this->activeTab = $this->normalizeTabName($this->activeTab);
+ $this->resetTable();
+ }
+
+ protected function getForms(): array
+ {
+ return [
+ 'backupsForm',
+ ];
+ }
+
+ public function backupsForm(Schema $schema): Schema
+ {
+ return $schema
+ ->schema([
+ Section::make(__('Recommendation'))
+ ->description(__('Use Incremental Backups for scheduled server backups. They only store changes since the last backup, significantly reducing storage space and backup time while maintaining full restore capability.'))
+ ->icon('heroicon-o-light-bulb')
+ ->iconColor('info')
+ ->collapsed(false)
+ ->collapsible(false),
+ Tabs::make(__('Backup Sections'))
+ ->contained()
+ ->livewireProperty('activeTab')
+ ->tabs([
+ 'destinations' => Tab::make(__('Destinations'))
+ ->icon('heroicon-o-server-stack')
+ ->schema([
+ View::make('filament.admin.pages.backups-tab-table'),
+ ]),
+ 'schedules' => Tab::make(__('Schedules'))
+ ->icon('heroicon-o-calendar-days')
+ ->schema([
+ View::make('filament.admin.pages.backups-tab-table'),
+ ]),
+ 'backups' => Tab::make(__('Backups'))
+ ->icon('heroicon-o-archive-box')
+ ->schema([
+ View::make('filament.admin.pages.backups-tab-table'),
+ ]),
+ ]),
+ ]);
+ }
+
+ public function getAgent(): AgentClient
+ {
+ return $this->agent ??= new AgentClient;
+ }
+
+ protected function supportsIncremental($destinationId): bool
+ {
+ if (empty($destinationId)) {
+ return false;
+ }
+
+ $destination = BackupDestination::find($destinationId);
+ if (! $destination) {
+ return false;
+ }
+
+ return in_array($destination->type, ['sftp', 'nfs']);
+ }
+
+ public function table(Table $table): Table
+ {
+ return match ($this->activeTab) {
+ 'destinations' => $this->destinationsTable($table),
+ 'schedules' => $this->schedulesTable($table),
+ 'backups' => $this->backupsTable($table),
+ default => $this->destinationsTable($table),
+ };
+ }
+
+ protected function destinationsTable(Table $table): Table
+ {
+ return $table
+ ->query(BackupDestination::query()->where('is_server_backup', true)->orderBy('name'))
+ ->columns([
+ TextColumn::make('name')
+ ->label(__('Name'))
+ ->weight('medium')
+ ->description(fn (BackupDestination $record): ?string => $record->is_default ? __('Default') : null)
+ ->searchable(),
+ TextColumn::make('type')
+ ->label(__('Type'))
+ ->badge()
+ ->formatStateUsing(fn (string $state): string => strtoupper($state))
+ ->color(fn (string $state): string => match ($state) {
+ 'sftp' => 'info',
+ 'nfs' => 'warning',
+ 's3' => 'success',
+ default => 'gray',
+ }),
+ TextColumn::make('test_status')
+ ->label(__('Status'))
+ ->badge()
+ ->formatStateUsing(fn (?string $state): string => match ($state) {
+ 'success' => __('Connected'),
+ 'failed' => __('Failed'),
+ default => __('Not Tested'),
+ })
+ ->color(fn (?string $state): string => match ($state) {
+ 'success' => 'success',
+ 'failed' => 'danger',
+ default => 'gray',
+ }),
+ TextColumn::make('last_tested_at')
+ ->label(__('Last Tested'))
+ ->since()
+ ->placeholder(__('Never'))
+ ->color('gray'),
+ ])
+ ->recordActions([
+ Action::make('test')
+ ->label(__('Test'))
+ ->icon('heroicon-o-check-circle')
+ ->color('success')
+ ->size('sm')
+ ->action(fn (BackupDestination $record) => $this->testDestination($record->id)),
+ Action::make('delete')
+ ->label(__('Delete'))
+ ->icon('heroicon-o-trash')
+ ->color('danger')
+ ->size('sm')
+ ->requiresConfirmation()
+ ->action(fn (BackupDestination $record) => $this->deleteDestination($record->id)),
+ ])
+ ->emptyStateHeading(__('No remote destinations configured'))
+ ->emptyStateDescription(__('Click "Add Destination" to configure SFTP, NFS, or S3 storage'))
+ ->emptyStateIcon('heroicon-o-server-stack')
+ ->striped();
+ }
+
+ protected function schedulesTable(Table $table): Table
+ {
+ return $table
+ ->query(BackupSchedule::query()->where('is_server_backup', true)->with('destination')->orderBy('name'))
+ ->columns([
+ TextColumn::make('name')
+ ->label(__('Name'))
+ ->weight('medium')
+ ->searchable(),
+ TextColumn::make('frequency_label')
+ ->label(__('Frequency')),
+ TextColumn::make('destination.name')
+ ->label(__('Destination'))
+ ->placeholder(__('Local')),
+ TextColumn::make('retention_count')
+ ->label(__('Retention'))
+ ->formatStateUsing(fn (int $state): string => $state.' '.__('backups')),
+ TextColumn::make('last_run_at')
+ ->label(__('Last Run'))
+ ->since()
+ ->dateTimeTooltip('M j, Y H:i T', timezone: $this->getSystemTimezone())
+ ->placeholder(__('Never'))
+ ->color('gray'),
+ TextColumn::make('next_run_at')
+ ->label(__('Next Run'))
+ ->since()
+ ->dateTimeTooltip('M j, Y H:i T', timezone: $this->getSystemTimezone())
+ ->placeholder(__('Not scheduled'))
+ ->color('gray'),
+ ViewColumn::make('status')
+ ->label(__('Status'))
+ ->view('filament.admin.columns.schedule-status'),
+ ])
+ ->recordActions([
+ Action::make('run')
+ ->label(__('Run'))
+ ->icon('heroicon-o-play')
+ ->color('gray')
+ ->size('sm')
+ ->visible(fn (BackupSchedule $record): bool => ! Backup::where('schedule_id', $record->id)->running()->exists())
+ ->action(fn (BackupSchedule $record) => $this->runScheduleNow($record->id)),
+ Action::make('stop')
+ ->label(__('Stop'))
+ ->icon('heroicon-o-stop')
+ ->color('danger')
+ ->size('sm')
+ ->visible(fn (BackupSchedule $record): bool => Backup::where('schedule_id', $record->id)->running()->exists())
+ ->requiresConfirmation()
+ ->action(fn (BackupSchedule $record) => $this->stopScheduleBackup($record->id)),
+ Action::make('edit')
+ ->label(__('Edit'))
+ ->icon('heroicon-o-pencil')
+ ->color('gray')
+ ->size('sm')
+ ->action(fn (BackupSchedule $record) => $this->mountAction('editSchedule', ['id' => $record->id])),
+ Action::make('toggle')
+ ->label(fn (BackupSchedule $record): string => $record->is_active ? __('Disable') : __('Enable'))
+ ->icon(fn (BackupSchedule $record): string => $record->is_active ? 'heroicon-o-pause' : 'heroicon-o-play')
+ ->color('gray')
+ ->size('sm')
+ ->action(fn (BackupSchedule $record) => $this->toggleSchedule($record->id)),
+ Action::make('delete')
+ ->label(__('Delete'))
+ ->icon('heroicon-o-trash')
+ ->color('danger')
+ ->size('sm')
+ ->requiresConfirmation()
+ ->action(fn (BackupSchedule $record) => $this->deleteSchedule($record->id)),
+ ])
+ ->headerActions([
+ $this->addScheduleAction(),
+ ])
+ ->emptyStateHeading(__('No backup schedules configured'))
+ ->emptyStateDescription(__('Click "Add Schedule" to set up automatic backups'))
+ ->emptyStateIcon('heroicon-o-clock')
+ ->striped()
+ ->poll(fn () => Backup::running()->exists() ? '3s' : null);
+ }
+
+ protected function backupsTable(Table $table): Table
+ {
+ return $table
+ ->query(Backup::query()->where('type', 'server')->with(['destination', 'user'])->orderByDesc('created_at')->limit(50))
+ ->columns([
+ TextColumn::make('name')
+ ->label(__('Name'))
+ ->weight('medium')
+ ->searchable()
+ ->limit(40),
+ ViewColumn::make('status')
+ ->label(__('Status'))
+ ->view('filament.admin.columns.backup-status'),
+ TextColumn::make('size_bytes')
+ ->label(__('Size'))
+ ->formatStateUsing(fn (Backup $record): string => $record->size_human),
+ TextColumn::make('destination.name')
+ ->label(__('Destination'))
+ ->placeholder(__('Local')),
+ TextColumn::make('created_at')
+ ->label(__('Created'))
+ ->dateTime('M j, Y H:i')
+ ->color('gray'),
+ TextColumn::make('duration')
+ ->label(__('Duration'))
+ ->placeholder('-')
+ ->color('gray'),
+ ])
+ ->recordActions([
+ Action::make('restore')
+ ->label(__('Restore'))
+ ->icon('heroicon-o-arrow-path')
+ ->color('warning')
+ ->size('sm')
+ ->visible(fn (Backup $record): bool => $record->status === 'completed' && ($record->local_path || $record->remote_path))
+ ->modalHeading(__('Restore Backup'))
+ ->modalDescription(__('Select what you want to restore. Warning: Existing data may be overwritten.'))
+ ->modalWidth('xl')
+ ->form(function (Backup $record): array {
+ // Check if this is a remote backup (no local files)
+ $isRemoteBackup = ! $record->local_path || ! file_exists($record->local_path);
+
+ $manifest = $this->getBackupManifest($record);
+ $users = $manifest['users'] ?? $record->users ?? [];
+ if (empty($users)) {
+ $users = [$manifest['username'] ?? ''];
+ }
+ $users = array_filter($users);
+
+ $isServerBackup = ($manifest['type'] ?? $record->type) === 'server' && count($users) > 1;
+
+ // For server backups, get data for first user by default
+ $selectedUser = $users[0] ?? '';
+ if ($isServerBackup && ! empty($selectedUser) && ! $isRemoteBackup) {
+ $manifest = $this->getBackupManifest($record, $selectedUser);
+ }
+
+ // For remote backups, use include_* flags from record
+ if ($isRemoteBackup) {
+ $hasFiles = $record->include_files ?? true;
+ $hasDatabases = $record->include_databases ?? true;
+ $hasMailboxes = $record->include_mailboxes ?? true;
+ $hasDns = $record->include_dns ?? true;
+ $hasSsl = true; // Assume SSL is included
+ $domains = [];
+ $databases = [];
+ $mailboxes = [];
+ } else {
+ $domains = $manifest['domains'] ?? [];
+ $databases = $manifest['databases'] ?? [];
+ $mailboxes = $manifest['mailboxes'] ?? [];
+ $hasFiles = ! empty($domains);
+ $hasDatabases = ! empty($databases);
+ $hasMailboxes = ! empty($mailboxes);
+ $hasDns = ! empty($manifest['dns_zones'] ?? []);
+ $hasSsl = ! empty($manifest['ssl_certificates'] ?? []);
+ }
+
+ $schema = [];
+
+ // Backup info section
+ $infoSchema = [
+ TextInput::make('backup_name')
+ ->label(__('Backup'))
+ ->default($record->name)
+ ->disabled(),
+ ];
+
+ // Add user selector for server backups with multiple users
+ if ($isServerBackup || count($users) > 1) {
+ $userOptions = [
+ '__all__' => __('All users'),
+ ];
+ foreach ($users as $userOption) {
+ $userOptions[$userOption] = $userOption;
+ }
+ $infoSchema[] = Select::make('restore_username')
+ ->label(__('User to Restore'))
+ ->options($userOptions)
+ ->default($selectedUser)
+ ->required()
+ ->helperText(__('Backup contains :count user(s)', ['count' => count($users)]));
+ } else {
+ $infoSchema[] = TextInput::make('restore_username')
+ ->label(__('User'))
+ ->default($selectedUser)
+ ->disabled();
+ }
+
+ $schema[] = Section::make(__('Backup Information'))
+ ->schema([Grid::make(2)->schema($infoSchema)]);
+
+ // Remote backup notice
+ if ($isRemoteBackup) {
+ $schema[] = Section::make(__('Remote Backup'))
+ ->description(__('This backup will be downloaded from the remote destination before restoring.'))
+ ->icon('heroicon-o-cloud-arrow-down')
+ ->iconColor('info');
+ }
+
+ // Restore options section
+ $restoreOptions = [];
+
+ // Website Files
+ $filesLabel = __('Website Files');
+ if (! $isRemoteBackup && ! empty($domains)) {
+ $filesLabel .= ' ('.count($domains).')';
+ }
+ $restoreOptions[] = Toggle::make('restore_files')
+ ->label($filesLabel)
+ ->helperText($isRemoteBackup
+ ? __('Restore all domain files')
+ : (! empty($domains) ? implode(', ', array_slice($domains, 0, 3)).(count($domains) > 3 ? '...' : '') : __('No files')))
+ ->default($hasFiles)
+ ->disabled(! $hasFiles && ! $isRemoteBackup);
+
+ if (! $isRemoteBackup && count($domains) > 1) {
+ $restoreOptions[] = Select::make('selected_domains')
+ ->label(__('Specific Domains'))
+ ->multiple()
+ ->options(fn () => array_combine($domains, $domains))
+ ->placeholder(__('All domains'))
+ ->visible(fn ($get) => $get('restore_files'));
+ }
+
+ // Databases
+ $dbLabel = __('Databases');
+ if (! $isRemoteBackup && ! empty($databases)) {
+ $dbLabel .= ' ('.count($databases).')';
+ }
+ $restoreOptions[] = Toggle::make('restore_databases')
+ ->label($dbLabel)
+ ->helperText($isRemoteBackup
+ ? __('Restore all databases')
+ : (! empty($databases) ? implode(', ', array_slice($databases, 0, 3)).(count($databases) > 3 ? '...' : '') : __('No databases')))
+ ->default($hasDatabases)
+ ->disabled(! $hasDatabases && ! $isRemoteBackup);
+
+ if (! $isRemoteBackup && count($databases) > 1) {
+ $restoreOptions[] = Select::make('selected_databases')
+ ->label(__('Specific Databases'))
+ ->multiple()
+ ->options(fn () => array_combine($databases, $databases))
+ ->placeholder(__('All databases'))
+ ->visible(fn ($get) => $get('restore_databases'));
+ }
+
+ // MySQL Users
+ $restoreOptions[] = Toggle::make('restore_mysql_users')
+ ->label(__('MySQL Users'))
+ ->default($hasDatabases)
+ ->helperText(__('Restore MySQL users and their permissions'));
+
+ // Mailboxes
+ $mailLabel = __('Mailboxes');
+ if (! $isRemoteBackup && ! empty($mailboxes)) {
+ $mailLabel .= ' ('.count($mailboxes).')';
+ }
+ $restoreOptions[] = Toggle::make('restore_mailboxes')
+ ->label($mailLabel)
+ ->helperText($isRemoteBackup
+ ? __('Restore all mailboxes')
+ : (! empty($mailboxes) ? implode(', ', array_slice($mailboxes, 0, 3)).(count($mailboxes) > 3 ? '...' : '') : __('No mailboxes')))
+ ->default($hasMailboxes)
+ ->disabled(! $hasMailboxes && ! $isRemoteBackup);
+
+ // SSL Certificates
+ $restoreOptions[] = Toggle::make('restore_ssl')
+ ->label(__('SSL Certificates'))
+ ->default(false)
+ ->helperText(__('Restore SSL certificates for domains'));
+
+ // DNS Zones
+ $restoreOptions[] = Toggle::make('restore_dns')
+ ->label(__('DNS Zones'))
+ ->default($hasDns)
+ ->helperText(__('Restore DNS zone files'));
+
+ $schema[] = Section::make(__('Restore Options'))
+ ->description(__('Toggle items you want to restore.'))
+ ->schema($restoreOptions);
+
+ return $schema;
+ })
+ ->action(function (array $data, Backup $record): void {
+ $this->executeRestore($record, $data);
+ })
+ ->modalSubmitActionLabel(__('Restore'))
+ ->requiresConfirmation(),
+ Action::make('download')
+ ->label(__('Download'))
+ ->icon('heroicon-o-arrow-down-tray')
+ ->color('gray')
+ ->size('sm')
+ ->visible(fn (Backup $record): bool => $record->canDownload())
+ ->url(fn (Backup $record): string => route('filament.admin.pages.backup-download', ['id' => $record->id]))
+ ->openUrlInNewTab(),
+ Action::make('delete')
+ ->label(__('Delete'))
+ ->icon('heroicon-o-trash')
+ ->color('danger')
+ ->size('sm')
+ ->requiresConfirmation()
+ ->action(fn (Backup $record) => $this->deleteBackup($record->id)),
+ ])
+ ->emptyStateHeading(__('No server backups yet'))
+ ->emptyStateDescription(__('Click "Create Server Backup" to create your first backup'))
+ ->emptyStateIcon('heroicon-o-archive-box')
+ ->striped()
+ ->poll(fn () => Backup::whereIn('status', ['pending', 'running', 'uploading'])->exists() ? '3s' : null);
+ }
+
+ public function getTableRecordKey(Model|array $record): string
+ {
+ return is_array($record) ? (string) $record['id'] : (string) $record->getKey();
+ }
+
+ protected function getHeaderActions(): array
+ {
+ return [
+ Action::make('createServerBackup')
+ ->label(__('Create Server Backup'))
+ ->icon('heroicon-o-archive-box-arrow-down')
+ ->color('primary')
+ ->form([
+ TextInput::make('name')
+ ->label(__('Backup Name'))
+ ->default(fn () => __('Server Backup').' '.now()->format('Y-m-d H:i'))
+ ->required(),
+ Select::make('destination_id')
+ ->label(__('Destination'))
+ ->options(fn () => BackupDestination::where('is_server_backup', true)
+ ->where('is_active', true)
+ ->pluck('name', 'id')
+ ->prepend(__('Local Storage'), ''))
+ ->default('')
+ ->live()
+ ->afterStateUpdated(fn ($set, $state) => $set('backup_type', $this->supportsIncremental($state) ? 'incremental' : 'full')),
+ Radio::make('backup_type')
+ ->label(__('Backup Type'))
+ ->options(fn ($get) => $this->supportsIncremental($get('destination_id'))
+ ? [
+ 'incremental' => __('Incremental (rsync) - Space-efficient'),
+ 'full' => __('Full (tar.gz) - Complete archive'),
+ ]
+ : [
+ 'full' => __('Full (tar.gz) - Complete archive'),
+ ])
+ ->default('full')
+ ->required(),
+ TextInput::make('local_path')
+ ->label(__('Local Backup Folder'))
+ ->default('/var/backups/jabali')
+ ->visible(fn ($get) => empty($get('destination_id'))),
+ Section::make(__('Include'))
+ ->schema([
+ Grid::make(2)->schema([
+ Toggle::make('include_files')->label(__('Website Files'))->default(true),
+ Toggle::make('include_databases')->label(__('Databases'))->default(true),
+ Toggle::make('include_mailboxes')->label(__('Mailboxes'))->default(true),
+ Toggle::make('include_dns')->label(__('DNS Records'))->default(true),
+ ]),
+ ]),
+ Select::make('users')
+ ->label(__('Users to Backup'))
+ ->multiple()
+ ->options(fn () => User::where('is_admin', false)
+ ->where('is_active', true)
+ ->pluck('username', 'username'))
+ ->placeholder(__('All Users')),
+ ])
+ ->action(function (array $data) {
+ $this->createServerBackup($data);
+ }),
+
+ $this->createUserBackupAction(),
+
+ Action::make('addDestination')
+ ->label(__('Add Destination'))
+ ->icon('heroicon-o-plus')
+ ->color('gray')
+ ->form($this->getDestinationForm())
+ ->action(function (array $data) {
+ $this->saveDestination($data);
+ }),
+ ];
+ }
+
+ protected function getDestinationForm(): array
+ {
+ return [
+ TextInput::make('name')
+ ->label(__('Destination Name'))
+ ->required(),
+ Select::make('type')
+ ->label(__('Type'))
+ ->options([
+ 'sftp' => __('SFTP Server'),
+ 'nfs' => __('NFS Mount'),
+ 's3' => __('S3-Compatible Storage'),
+ ])
+ ->required()
+ ->live(),
+
+ Section::make(__('SFTP Settings'))
+ ->visible(fn ($get) => $get('type') === 'sftp')
+ ->schema([
+ Grid::make(2)->schema([
+ TextInput::make('host')->label(__('Host'))->required(),
+ TextInput::make('port')->label(__('Port'))->numeric()->default(22),
+ ]),
+ TextInput::make('username')->label(__('Username'))->required(),
+ TextInput::make('password')->label(__('Password'))->password(),
+ Textarea::make('private_key')->label(__('Private Key (SSH)'))->rows(4),
+ TextInput::make('path')->label(__('Remote Path'))->default('/backups'),
+ ]),
+
+ Section::make(__('NFS Settings'))
+ ->visible(fn ($get) => $get('type') === 'nfs')
+ ->schema([
+ TextInput::make('server')->label(__('NFS Server'))->required(),
+ TextInput::make('share')->label(__('Share Path'))->required(),
+ TextInput::make('path')->label(__('Sub-directory'))->default(''),
+ ]),
+
+ Section::make(__('S3-Compatible Settings'))
+ ->visible(fn ($get) => $get('type') === 's3')
+ ->schema([
+ TextInput::make('endpoint')->label(__('Endpoint URL')),
+ TextInput::make('bucket')->label(__('Bucket Name'))->required(),
+ Grid::make(2)->schema([
+ TextInput::make('access_key')->label(__('Access Key ID'))->required(),
+ TextInput::make('secret_key')->label(__('Secret Access Key'))->password()->required(),
+ ]),
+ TextInput::make('region')->label(__('Region'))->default('us-east-1'),
+ TextInput::make('path')->label(__('Path Prefix'))->default('backups'),
+ ]),
+
+ Toggle::make('is_default')->label(__('Set as Default Destination')),
+
+ FormActions::make([
+ Action::make('testConnection')
+ ->label(__('Test Connection'))
+ ->icon('heroicon-o-signal')
+ ->color('gray')
+ ->action(function ($get, $livewire) {
+ $type = $get('type');
+ if (empty($type)) {
+ Notification::make()
+ ->title(__('Select a destination type first'))
+ ->warning()
+ ->send();
+
+ return;
+ }
+
+ $config = match ($type) {
+ 'sftp' => [
+ 'type' => 'sftp',
+ 'host' => $get('host') ?? '',
+ 'port' => (int) ($get('port') ?? 22),
+ 'username' => $get('username') ?? '',
+ 'password' => $get('password') ?? '',
+ 'private_key' => $get('private_key') ?? '',
+ 'path' => $get('path') ?? '/backups',
+ ],
+ 'nfs' => [
+ 'type' => 'nfs',
+ 'server' => $get('server') ?? '',
+ 'share' => $get('share') ?? '',
+ 'path' => $get('path') ?? '',
+ ],
+ 's3' => [
+ 'type' => 's3',
+ 'endpoint' => $get('endpoint') ?? '',
+ 'bucket' => $get('bucket') ?? '',
+ 'access_key' => $get('access_key') ?? '',
+ 'secret_key' => $get('secret_key') ?? '',
+ 'region' => $get('region') ?? 'us-east-1',
+ 'path' => $get('path') ?? 'backups',
+ ],
+ default => [],
+ };
+
+ if (empty($config)) {
+ Notification::make()
+ ->title(__('Invalid destination type'))
+ ->danger()
+ ->send();
+
+ return;
+ }
+
+ try {
+ $result = $livewire->getAgent()->backupTestDestination($config);
+ if ($result['success']) {
+ Notification::make()
+ ->title(__('Connection successful'))
+ ->body(__('The destination is reachable and ready to use.'))
+ ->success()
+ ->send();
+ } else {
+ Notification::make()
+ ->title(__('Connection failed'))
+ ->body($result['error'] ?? __('Could not connect to destination'))
+ ->danger()
+ ->send();
+ }
+ } catch (Exception $e) {
+ Notification::make()
+ ->title(__('Connection test failed'))
+ ->body($e->getMessage())
+ ->danger()
+ ->send();
+ }
+ }),
+ ])->visible(fn ($get) => ! empty($get('type'))),
+ ];
+ }
+
+ public function saveDestination(array $data): void
+ {
+ $config = [];
+ $type = $data['type'];
+
+ switch ($type) {
+ case 'sftp':
+ $config = [
+ 'host' => $data['host'] ?? '',
+ 'port' => (int) ($data['port'] ?? 22),
+ 'username' => $data['username'] ?? '',
+ 'password' => $data['password'] ?? '',
+ 'private_key' => $data['private_key'] ?? '',
+ 'path' => $data['path'] ?? '/backups',
+ ];
+ break;
+
+ case 'nfs':
+ $config = [
+ 'server' => $data['server'] ?? '',
+ 'share' => $data['share'] ?? '',
+ 'path' => $data['path'] ?? '',
+ ];
+ break;
+
+ case 's3':
+ $config = [
+ 'endpoint' => $data['endpoint'] ?? '',
+ 'bucket' => $data['bucket'] ?? '',
+ 'access_key' => $data['access_key'] ?? '',
+ 'secret_key' => $data['secret_key'] ?? '',
+ 'region' => $data['region'] ?? 'us-east-1',
+ 'path' => $data['path'] ?? 'backups',
+ ];
+ break;
+ }
+
+ $testConfig = array_merge($config, ['type' => $type]);
+ try {
+ $result = $this->getAgent()->backupTestDestination($testConfig);
+ if (! $result['success']) {
+ Notification::make()
+ ->title(__('Connection failed'))
+ ->body($result['error'] ?? __('Could not connect to destination'))
+ ->danger()
+ ->send();
+
+ return;
+ }
+ } catch (Exception $e) {
+ Notification::make()
+ ->title(__('Connection test failed'))
+ ->body($e->getMessage())
+ ->danger()
+ ->send();
+
+ return;
+ }
+
+ BackupDestination::create([
+ 'name' => $data['name'],
+ 'type' => $type,
+ 'config' => $config,
+ 'is_server_backup' => true,
+ 'is_default' => $data['is_default'] ?? false,
+ 'is_active' => true,
+ 'last_tested_at' => now(),
+ 'test_status' => 'success',
+ ]);
+
+ Notification::make()->title(__('Destination verified and added'))->success()->send();
+ $this->resetTable();
+ }
+
+ public function testDestination(int $id): void
+ {
+ $destination = BackupDestination::find($id);
+ if (! $destination) {
+ return;
+ }
+
+ try {
+ $config = array_merge($destination->config ?? [], ['type' => $destination->type]);
+ $result = $this->getAgent()->backupTestDestination($config);
+
+ $destination->update([
+ 'last_tested_at' => now(),
+ 'test_status' => $result['success'] ? 'success' : 'failed',
+ 'test_message' => $result['message'] ?? $result['error'] ?? null,
+ ]);
+
+ if ($result['success']) {
+ Notification::make()->title(__('Connection successful'))->success()->send();
+ } else {
+ Notification::make()->title(__('Connection failed'))->body($result['error'] ?? __('Unknown error'))->danger()->send();
+ }
+ } catch (Exception $e) {
+ $destination->update([
+ 'last_tested_at' => now(),
+ 'test_status' => 'failed',
+ 'test_message' => $e->getMessage(),
+ ]);
+ Notification::make()->title(__('Test failed'))->body($e->getMessage())->danger()->send();
+ }
+
+ $this->resetTable();
+ }
+
+ public function deleteDestination(int $id): void
+ {
+ BackupDestination::where('id', $id)->delete();
+ Notification::make()->title(__('Destination deleted'))->success()->send();
+ $this->resetTable();
+ }
+
+ public function createServerBackup(array $data): void
+ {
+ $backupType = $data['backup_type'] ?? 'full';
+ $timestamp = now()->format('Y-m-d_His');
+ $folderName = $timestamp;
+ $baseFolder = rtrim($data['local_path'] ?? '/var/backups/jabali', '/');
+ $outputPath = "{$baseFolder}/{$folderName}";
+
+ $isIncrementalRemote = $backupType === 'incremental' && ! empty($data['destination_id']);
+
+ if ($isIncrementalRemote) {
+ $destination = BackupDestination::find($data['destination_id']);
+ if (! $destination || ! in_array($destination->type, ['sftp', 'nfs'])) {
+ Notification::make()
+ ->title(__('Invalid destination'))
+ ->body(__('Incremental backups require an SFTP or NFS destination'))
+ ->danger()
+ ->send();
+
+ return;
+ }
+ }
+
+ // Create backup record with pending status
+ $backup = Backup::create([
+ 'name' => $data['name'],
+ 'filename' => $folderName,
+ 'type' => 'server',
+ 'include_files' => $data['include_files'] ?? true,
+ 'include_databases' => $data['include_databases'] ?? true,
+ 'include_mailboxes' => $data['include_mailboxes'] ?? true,
+ 'include_dns' => $data['include_dns'] ?? true,
+ 'users' => ! empty($data['users']) ? $data['users'] : null,
+ 'destination_id' => ! empty($data['destination_id']) ? $data['destination_id'] : null,
+ 'schedule_id' => $data['schedule_id'] ?? null,
+ 'status' => 'pending',
+ 'local_path' => $isIncrementalRemote ? null : $outputPath,
+ 'metadata' => ['backup_type' => $backupType],
+ ]);
+
+ // Dispatch job to run backup in background
+ \App\Jobs\RunServerBackup::dispatch($backup->id);
+
+ // Show notification and refresh table
+ Notification::make()
+ ->title(__('Backup started'))
+ ->body(__('The backup is running in the background. The status will update automatically.'))
+ ->info()
+ ->send();
+
+ $this->resetTable();
+ }
+
+ protected function uploadToRemote(Backup $backup, bool $keepLocal = false): bool
+ {
+ if (! $backup->destination || ! $backup->local_path) {
+ return false;
+ }
+
+ try {
+ $backup->update(['status' => 'uploading']);
+
+ $config = array_merge($backup->destination->config ?? [], ['type' => $backup->destination->type]);
+ $backupType = $backup->metadata['backup_type'] ?? 'full';
+ $result = $this->getAgent()->backupUploadRemote($backup->local_path, $config, $backupType);
+
+ if ($result['success']) {
+ $backup->update([
+ 'status' => 'completed',
+ 'remote_path' => $result['remote_path'] ?? null,
+ ]);
+
+ if (! $keepLocal && $backup->local_path) {
+ $this->getAgent()->backupDeleteServer($backup->local_path);
+ $backup->update(['local_path' => null]);
+ }
+
+ return true;
+ } else {
+ throw new Exception($result['error'] ?? __('Upload failed'));
+ }
+ } catch (Exception $e) {
+ $backup->update([
+ 'status' => 'completed',
+ 'error_message' => __('Remote upload failed').': '.$e->getMessage(),
+ ]);
+
+ return false;
+ }
+ }
+
+ public function deleteBackup(int $id): void
+ {
+ $backup = Backup::find($id);
+ if (! $backup) {
+ return;
+ }
+
+ // Delete local file/folder
+ if ($backup->local_path && file_exists($backup->local_path)) {
+ if (is_file($backup->local_path)) {
+ unlink($backup->local_path);
+ } else {
+ exec('rm -rf '.escapeshellarg($backup->local_path));
+ }
+ }
+
+ // Delete from remote destination if exists
+ if ($backup->remote_path && $backup->destination) {
+ try {
+ $config = array_merge(
+ $backup->destination->config ?? [],
+ ['type' => $backup->destination->type]
+ );
+ $this->getAgent()->send('backup.delete_remote', [
+ 'remote_path' => $backup->remote_path,
+ 'destination' => $config,
+ ]);
+ } catch (Exception $e) {
+ // Log but continue - we still want to delete the DB record
+ logger()->warning('Failed to delete remote backup: '.$e->getMessage());
+ }
+ }
+
+ $backup->delete();
+ Notification::make()->title(__('Backup deleted'))->success()->send();
+ $this->resetTable();
+ }
+
+ public function addScheduleAction(): Action
+ {
+ return Action::make('addSchedule')
+ ->label(__('Add Schedule'))
+ ->icon('heroicon-o-clock')
+ ->color('primary')
+ ->form([
+ TextInput::make('name')
+ ->label(__('Schedule Name'))
+ ->required(),
+ Select::make('destination_id')
+ ->label(__('Destination'))
+ ->options(fn () => BackupDestination::where('is_server_backup', true)
+ ->where('is_active', true)
+ ->pluck('name', 'id')
+ ->prepend(__('Local Storage'), ''))
+ ->default('')
+ ->live()
+ ->afterStateUpdated(fn ($set, $state) => $set('backup_type', $this->supportsIncremental($state) ? 'incremental' : 'full')),
+ Radio::make('backup_type')
+ ->label(__('Backup Type'))
+ ->options(fn ($get) => $this->supportsIncremental($get('destination_id'))
+ ? [
+ 'incremental' => __('Incremental (rsync)'),
+ 'full' => __('Full (tar.gz)'),
+ ]
+ : [
+ 'full' => __('Full (tar.gz)'),
+ ])
+ ->default('full')
+ ->required(),
+ Select::make('frequency')
+ ->label(__('Frequency'))
+ ->options([
+ 'hourly' => __('Hourly'),
+ 'daily' => __('Daily'),
+ 'weekly' => __('Weekly'),
+ 'monthly' => __('Monthly'),
+ ])
+ ->required()
+ ->live(),
+ TextInput::make('time')
+ ->label(__('Time (HH:MM)'))
+ ->default('02:00')
+ ->visible(fn ($get) => in_array($get('frequency'), ['daily', 'weekly', 'monthly'])),
+ Select::make('day_of_week')
+ ->label(__('Day of Week'))
+ ->options([
+ 0 => __('Sunday'), 1 => __('Monday'), 2 => __('Tuesday'),
+ 3 => __('Wednesday'), 4 => __('Thursday'), 5 => __('Friday'), 6 => __('Saturday'),
+ ])
+ ->visible(fn ($get) => $get('frequency') === 'weekly'),
+ Select::make('day_of_month')
+ ->label(__('Day of Month'))
+ ->options(array_combine(range(1, 28), range(1, 28)))
+ ->visible(fn ($get) => $get('frequency') === 'monthly'),
+ TextInput::make('retention_count')
+ ->label(__('Keep Last N Backups'))
+ ->numeric()
+ ->default(7),
+ Section::make(__('Include'))
+ ->schema([
+ Grid::make(2)->schema([
+ Toggle::make('include_files')->label(__('Website Files'))->default(true),
+ Toggle::make('include_databases')->label(__('Databases'))->default(true),
+ Toggle::make('include_mailboxes')->label(__('Mailboxes'))->default(true),
+ Toggle::make('include_dns')->label(__('DNS Records'))->default(true),
+ ]),
+ ]),
+ ])
+ ->action(function (array $data) {
+ $schedule = BackupSchedule::create([
+ 'name' => $data['name'],
+ 'is_server_backup' => true,
+ 'is_active' => true,
+ 'frequency' => $data['frequency'],
+ 'time' => $data['time'] ?? '02:00',
+ 'day_of_week' => $data['day_of_week'] ?? null,
+ 'day_of_month' => $data['day_of_month'] ?? null,
+ 'destination_id' => ! empty($data['destination_id']) ? $data['destination_id'] : null,
+ 'retention_count' => $data['retention_count'] ?? 7,
+ 'include_files' => $data['include_files'] ?? true,
+ 'include_databases' => $data['include_databases'] ?? true,
+ 'include_mailboxes' => $data['include_mailboxes'] ?? true,
+ 'include_dns' => $data['include_dns'] ?? true,
+ 'metadata' => ['backup_type' => $data['backup_type'] ?? 'full'],
+ ]);
+
+ $schedule->calculateNextRun();
+ $schedule->save();
+
+ Notification::make()->title(__('Schedule created'))->success()->send();
+ $this->resetTable();
+ });
+ }
+
+ public function toggleSchedule(int $id): void
+ {
+ $schedule = BackupSchedule::find($id);
+ if (! $schedule) {
+ return;
+ }
+
+ $schedule->update(['is_active' => ! $schedule->is_active]);
+
+ if ($schedule->is_active) {
+ $schedule->calculateNextRun();
+ $schedule->save();
+ }
+
+ Notification::make()->title($schedule->is_active ? __('Schedule enabled') : __('Schedule disabled'))->success()->send();
+ $this->resetTable();
+ }
+
+ public function deleteSchedule(int $id): void
+ {
+ BackupSchedule::where('id', $id)->delete();
+ Notification::make()->title(__('Schedule deleted'))->success()->send();
+ $this->resetTable();
+ }
+
+ public function editScheduleAction(): Action
+ {
+ return Action::make('editSchedule')
+ ->label(__('Edit Schedule'))
+ ->icon('heroicon-o-pencil')
+ ->color('gray')
+ ->fillForm(function (array $arguments): array {
+ $schedule = BackupSchedule::find($arguments['id']);
+ if (! $schedule) {
+ return [];
+ }
+
+ return [
+ 'name' => $schedule->name,
+ 'backup_type' => $schedule->metadata['backup_type'] ?? 'full',
+ 'frequency' => $schedule->frequency,
+ 'time' => $schedule->time,
+ 'day_of_week' => $schedule->day_of_week,
+ 'day_of_month' => $schedule->day_of_month,
+ 'destination_id' => $schedule->destination_id ?? '',
+ 'retention_count' => $schedule->retention_count,
+ 'include_files' => $schedule->include_files,
+ 'include_databases' => $schedule->include_databases,
+ 'include_mailboxes' => $schedule->include_mailboxes,
+ 'include_dns' => $schedule->include_dns,
+ ];
+ })
+ ->form([
+ TextInput::make('name')->label(__('Schedule Name'))->required(),
+ Select::make('destination_id')
+ ->label(__('Destination'))
+ ->options(fn () => BackupDestination::where('is_server_backup', true)
+ ->where('is_active', true)
+ ->pluck('name', 'id')
+ ->prepend(__('Local Storage'), ''))
+ ->default('')
+ ->live(),
+ Radio::make('backup_type')
+ ->label(__('Backup Type'))
+ ->options(fn ($get) => $this->supportsIncremental($get('destination_id'))
+ ? ['incremental' => __('Incremental'), 'full' => __('Full')]
+ : ['full' => __('Full')])
+ ->required(),
+ Select::make('frequency')
+ ->label(__('Frequency'))
+ ->options(['hourly' => __('Hourly'), 'daily' => __('Daily'), 'weekly' => __('Weekly'), 'monthly' => __('Monthly')])
+ ->required()
+ ->live(),
+ TextInput::make('time')->label(__('Time (HH:MM)'))->visible(fn ($get) => in_array($get('frequency'), ['daily', 'weekly', 'monthly'])),
+ Select::make('day_of_week')
+ ->label(__('Day of Week'))
+ ->options([0 => __('Sunday'), 1 => __('Monday'), 2 => __('Tuesday'), 3 => __('Wednesday'), 4 => __('Thursday'), 5 => __('Friday'), 6 => __('Saturday')])
+ ->visible(fn ($get) => $get('frequency') === 'weekly'),
+ Select::make('day_of_month')
+ ->label(__('Day of Month'))
+ ->options(array_combine(range(1, 28), range(1, 28)))
+ ->visible(fn ($get) => $get('frequency') === 'monthly'),
+ TextInput::make('retention_count')->label(__('Keep Last N Backups'))->numeric(),
+ Section::make(__('Include'))
+ ->schema([
+ Grid::make(2)->schema([
+ Toggle::make('include_files')->label(__('Website Files')),
+ Toggle::make('include_databases')->label(__('Databases')),
+ Toggle::make('include_mailboxes')->label(__('Mailboxes')),
+ Toggle::make('include_dns')->label(__('DNS Records')),
+ ]),
+ ]),
+ ])
+ ->action(function (array $data, array $arguments) {
+ $schedule = BackupSchedule::find($arguments['id']);
+ if (! $schedule) {
+ return;
+ }
+
+ $schedule->update([
+ 'name' => $data['name'],
+ 'frequency' => $data['frequency'],
+ 'time' => $data['time'] ?? '02:00',
+ 'day_of_week' => $data['day_of_week'] ?? null,
+ 'day_of_month' => $data['day_of_month'] ?? null,
+ 'destination_id' => ! empty($data['destination_id']) ? $data['destination_id'] : null,
+ 'retention_count' => $data['retention_count'] ?? 7,
+ 'include_files' => $data['include_files'] ?? true,
+ 'include_databases' => $data['include_databases'] ?? true,
+ 'include_mailboxes' => $data['include_mailboxes'] ?? true,
+ 'include_dns' => $data['include_dns'] ?? true,
+ 'metadata' => array_merge($schedule->metadata ?? [], ['backup_type' => $data['backup_type'] ?? 'full']),
+ ]);
+
+ $schedule->calculateNextRun();
+ $schedule->save();
+
+ Notification::make()->title(__('Schedule updated'))->success()->send();
+ $this->resetTable();
+ });
+ }
+
+ public function runScheduleNow(int $id): void
+ {
+ $schedule = BackupSchedule::find($id);
+ if (! $schedule) {
+ return;
+ }
+
+ $runningBackup = Backup::where('schedule_id', $id)->running()->first();
+ if ($runningBackup) {
+ Notification::make()->title(__('Backup already running'))->warning()->send();
+
+ return;
+ }
+
+ $this->createServerBackup([
+ 'name' => $schedule->name.' - '.__('Manual Run').' '.now()->format('Y-m-d H:i'),
+ 'backup_type' => $schedule->metadata['backup_type'] ?? 'full',
+ 'destination_id' => $schedule->destination_id,
+ 'schedule_id' => $schedule->id,
+ 'include_files' => $schedule->include_files,
+ 'include_databases' => $schedule->include_databases,
+ 'include_mailboxes' => $schedule->include_mailboxes,
+ 'include_dns' => $schedule->include_dns,
+ 'users' => $schedule->users,
+ ]);
+ }
+
+ public function stopScheduleBackup(int $id): void
+ {
+ $backup = Backup::where('schedule_id', $id)->running()->first();
+ if ($backup) {
+ $backup->update([
+ 'status' => 'failed',
+ 'error_message' => __('Cancelled by user'),
+ 'completed_at' => now(),
+ ]);
+ Notification::make()->title(__('Backup cancelled'))->success()->send();
+ $this->resetTable();
+ }
+ }
+
+ public function createUserBackupAction(): Action
+ {
+ return Action::make('createUserBackup')
+ ->label(__('Backup User'))
+ ->icon('heroicon-o-user')
+ ->color('gray')
+ ->form([
+ Select::make('user_id')
+ ->label(__('User'))
+ ->options(fn () => User::where('is_admin', false)
+ ->where('is_active', true)
+ ->pluck('username', 'id'))
+ ->required()
+ ->searchable(),
+ Section::make(__('Include'))
+ ->schema([
+ Grid::make(2)->schema([
+ Toggle::make('include_files')->label(__('Website Files'))->default(true),
+ Toggle::make('include_databases')->label(__('Databases'))->default(true),
+ Toggle::make('include_mailboxes')->label(__('Mailboxes'))->default(true),
+ Toggle::make('include_dns')->label(__('DNS Records'))->default(true),
+ ]),
+ ]),
+ ])
+ ->action(function (array $data) {
+ $user = User::find($data['user_id']);
+ if (! $user) {
+ Notification::make()->title(__('User not found'))->danger()->send();
+
+ return;
+ }
+
+ $timestamp = now()->format('Y-m-d_His');
+ $filename = "backup_{$timestamp}.tar.gz";
+ $outputPath = "/home/{$user->username}/backups/{$filename}";
+
+ $backup = Backup::create([
+ 'user_id' => $user->id,
+ 'name' => "{$user->username} ".__('Backup').' '.now()->format('Y-m-d H:i'),
+ 'filename' => $filename,
+ 'type' => 'full',
+ 'include_files' => $data['include_files'] ?? true,
+ 'include_databases' => $data['include_databases'] ?? true,
+ 'include_mailboxes' => $data['include_mailboxes'] ?? true,
+ 'include_dns' => $data['include_dns'] ?? true,
+ 'status' => 'pending',
+ 'local_path' => $outputPath,
+ 'metadata' => ['backup_type' => 'full'],
+ ]);
+
+ try {
+ $backup->update(['status' => 'running', 'started_at' => now()]);
+
+ $result = $this->getAgent()->backupCreate($user->username, $outputPath, [
+ 'backup_type' => 'full',
+ 'include_files' => $data['include_files'] ?? true,
+ 'include_databases' => $data['include_databases'] ?? true,
+ 'include_mailboxes' => $data['include_mailboxes'] ?? true,
+ 'include_dns' => $data['include_dns'] ?? true,
+ ]);
+
+ if ($result['success']) {
+ $backup->update([
+ 'status' => 'completed',
+ 'completed_at' => now(),
+ 'size_bytes' => $result['size'] ?? 0,
+ 'checksum' => $result['checksum'] ?? null,
+ 'domains' => $result['domains'] ?? null,
+ 'databases' => $result['databases'] ?? null,
+ 'mailboxes' => $result['mailboxes'] ?? null,
+ ]);
+ Notification::make()->title(__('Backup created for :username', ['username' => $user->username]))->success()->send();
+ } else {
+ throw new Exception($result['error'] ?? __('Backup failed'));
+ }
+ } catch (Exception $e) {
+ $backup->update([
+ 'status' => 'failed',
+ 'completed_at' => now(),
+ 'error_message' => $e->getMessage(),
+ ]);
+ Notification::make()->title(__('Backup failed'))->body($e->getMessage())->danger()->send();
+ }
+
+ $this->resetTable();
+ });
+ }
+
+ protected function executeRestore(Backup $backup, array $data): void
+ {
+ // Use username from form (allows selecting user for server backups)
+ $username = $data['restore_username'] ?? '';
+
+ if ($username === '__all__') {
+ $manifest = $this->getBackupManifest($backup);
+ $usernames = $manifest['users'] ?? $backup->users ?? [];
+ if (empty($usernames)) {
+ $usernames = array_filter([$manifest['username'] ?? '']);
+ }
+
+ if (empty($usernames)) {
+ Notification::make()->title(__('Cannot determine users for this backup'))->danger()->send();
+
+ return;
+ }
+
+ foreach ($usernames as $restoreUser) {
+ $data['restore_username'] = $restoreUser;
+ $this->executeRestore($backup, $data);
+ }
+
+ return;
+ }
+
+ if (empty($username)) {
+ $manifest = $this->getBackupManifest($backup);
+ $username = $manifest['username'] ?? ($backup->users[0] ?? '');
+ }
+
+ if (empty($username)) {
+ Notification::make()->title(__('Cannot determine user for this backup'))->danger()->send();
+
+ return;
+ }
+
+ // Prepare backup path
+ $backupPath = $backup->local_path;
+ $tempDownloadPath = null;
+
+ // For remote backups, download first
+ if ((! $backupPath || ! file_exists($backupPath)) && $backup->remote_path && $backup->destination) {
+ $destination = $backup->destination;
+
+ if (! $destination) {
+ Notification::make()->title(__('Backup destination not found'))->danger()->send();
+
+ return;
+ }
+
+ // Create temp directory for download
+ $tempDownloadPath = sys_get_temp_dir().'/jabali_restore_download_'.uniqid();
+ mkdir($tempDownloadPath, 0755, true);
+
+ // For incremental backups, we need to download the specific user's directory
+ $remotePath = $backup->remote_path;
+
+ // If it's a server backup with per-user directories, construct the user-specific path
+ if (str_contains($remotePath, '/') && ! str_ends_with($remotePath, '.tar.gz')) {
+ // Incremental backup - download the user's directory
+ $userRemotePath = rtrim($remotePath, '/').'/'.$username;
+ } else {
+ $userRemotePath = $remotePath;
+ }
+
+ Notification::make()
+ ->title(__('Downloading backup'))
+ ->body(__('Downloading from remote destination...'))
+ ->info()
+ ->send();
+
+ try {
+ $downloadResult = $this->getAgent()->send('backup.download_remote', [
+ 'remote_path' => $userRemotePath,
+ 'local_path' => $tempDownloadPath,
+ 'destination' => array_merge(
+ $destination->config ?? [],
+ ['type' => $destination->type]
+ ),
+ ]);
+
+ if (! ($downloadResult['success'] ?? false)) {
+ throw new Exception($downloadResult['error'] ?? __('Failed to download backup'));
+ }
+
+ $backupPath = $tempDownloadPath;
+ } catch (Exception $e) {
+ // Cleanup temp directory on failure
+ if (is_dir($tempDownloadPath)) {
+ exec('rm -rf '.escapeshellarg($tempDownloadPath));
+ }
+ Notification::make()
+ ->title(__('Download failed'))
+ ->body($e->getMessage())
+ ->danger()
+ ->send();
+
+ return;
+ }
+ }
+
+ if (! $backupPath || ! file_exists($backupPath)) {
+ Notification::make()->title(__('Backup file not found'))->danger()->send();
+
+ return;
+ }
+
+ try {
+ $result = $this->getAgent()->send('backup.restore', [
+ 'username' => $username,
+ 'backup_path' => $backupPath,
+ 'restore_files' => $data['restore_files'] ?? false,
+ 'restore_databases' => $data['restore_databases'] ?? false,
+ 'restore_mailboxes' => $data['restore_mailboxes'] ?? false,
+ 'restore_dns' => $data['restore_dns'] ?? false,
+ 'restore_ssl' => $data['restore_ssl'] ?? false,
+ 'selected_domains' => ! empty($data['selected_domains']) ? $data['selected_domains'] : null,
+ 'selected_databases' => ! empty($data['selected_databases']) ? $data['selected_databases'] : null,
+ 'selected_mailboxes' => ! empty($data['selected_mailboxes']) ? $data['selected_mailboxes'] : null,
+ ]);
+
+ // Cleanup temp download if used
+ if ($tempDownloadPath && is_dir($tempDownloadPath)) {
+ exec('rm -rf '.escapeshellarg($tempDownloadPath));
+ }
+
+ if ($result['success'] ?? false) {
+ $restored = $result['restored'] ?? [];
+ $summary = [];
+
+ if (! empty($restored['files'])) {
+ $summary[] = count($restored['files']).' '.__('domain(s)');
+ }
+ if (! empty($restored['databases'])) {
+ $summary[] = count($restored['databases']).' '.__('database(s)');
+ }
+ if (! empty($restored['mailboxes'])) {
+ $summary[] = count($restored['mailboxes']).' '.__('mailbox(es)');
+ }
+ if (! empty($restored['ssl_certificates'])) {
+ $summary[] = count($restored['ssl_certificates']).' '.__('SSL cert(s)');
+ }
+ if (! empty($restored['dns_zones'])) {
+ $summary[] = count($restored['dns_zones']).' '.__('DNS zone(s)');
+ }
+ if ($restored['mysql_users'] ?? false) {
+ $summary[] = __('MySQL users');
+ }
+
+ Notification::make()
+ ->title(__('Restore completed'))
+ ->body(! empty($summary) ? __('Restored: :items', ['items' => implode(', ', $summary)]) : __('Nothing was restored'))
+ ->success()
+ ->send();
+ } else {
+ throw new Exception($result['error'] ?? __('Restore failed'));
+ }
+ } catch (Exception $e) {
+ // Cleanup temp download on failure
+ if ($tempDownloadPath && is_dir($tempDownloadPath)) {
+ exec('rm -rf '.escapeshellarg($tempDownloadPath));
+ }
+ Notification::make()
+ ->title(__('Restore failed'))
+ ->body($e->getMessage())
+ ->danger()
+ ->send();
+ }
+ }
+
+ protected function getBackupManifest(Backup $backup, ?string $forUser = null): array
+ {
+ $backupPath = $backup->local_path;
+
+ if (! $backupPath || ! file_exists($backupPath)) {
+ // For remote backups, try to get info from stored metadata
+ return [
+ 'username' => $forUser ?? ($backup->users[0] ?? ''),
+ 'domains' => $backup->domains ?? [],
+ 'databases' => $backup->databases ?? [],
+ 'mailboxes' => $backup->mailboxes ?? [],
+ 'mysql_users' => $backup->metadata['mysql_users'] ?? [],
+ 'ssl_certificates' => $backup->ssl_certificates ?? [],
+ 'dns_zones' => $backup->dns_zones ?? [],
+ 'users' => $backup->users ?? [],
+ ];
+ }
+
+ try {
+ $result = $this->getAgent()->send('backup.get_info', [
+ 'backup_path' => $backupPath,
+ ]);
+
+ if ($result['success'] ?? false) {
+ $manifest = $result['manifest'] ?? [];
+
+ // Handle server backup manifest format (has nested 'users' object)
+ if (isset($manifest['users']) && is_array($manifest['users']) && $manifest['type'] === 'server') {
+ $userList = array_keys($manifest['users']);
+
+ // If no specific user requested, return aggregated data
+ if ($forUser === null) {
+ return [
+ 'username' => $userList[0] ?? '',
+ 'users' => $userList,
+ 'type' => 'server',
+ 'domains' => $this->aggregateFromUsers($manifest['users'], 'domains'),
+ 'databases' => $this->aggregateFromUsers($manifest['users'], 'databases'),
+ 'mailboxes' => $this->aggregateFromUsers($manifest['users'], 'mailboxes'),
+ 'mysql_users' => [],
+ 'ssl_certificates' => [],
+ 'dns_zones' => [],
+ ];
+ }
+
+ // Return specific user's data
+ if (isset($manifest['users'][$forUser])) {
+ $userData = $manifest['users'][$forUser];
+
+ return [
+ 'username' => $forUser,
+ 'users' => $userList,
+ 'type' => 'server',
+ 'domains' => $userData['domains'] ?? [],
+ 'databases' => $userData['databases'] ?? [],
+ 'mailboxes' => $userData['mailboxes'] ?? [],
+ 'mysql_users' => [],
+ 'ssl_certificates' => [],
+ 'dns_zones' => [],
+ ];
+ }
+ }
+
+ return $manifest;
+ }
+ } catch (Exception $e) {
+ // Fall back to stored data
+ }
+
+ return [
+ 'username' => $forUser ?? ($backup->users[0] ?? ''),
+ 'domains' => $backup->domains ?? [],
+ 'databases' => $backup->databases ?? [],
+ 'mailboxes' => $backup->mailboxes ?? [],
+ 'mysql_users' => [],
+ 'ssl_certificates' => [],
+ 'dns_zones' => [],
+ 'users' => $backup->users ?? [],
+ ];
+ }
+
+ protected function aggregateFromUsers(array $users, string $key): array
+ {
+ $result = [];
+ foreach ($users as $userData) {
+ if (isset($userData[$key]) && is_array($userData[$key])) {
+ $result = array_merge($result, $userData[$key]);
+ }
+ }
+
+ return array_unique($result);
+ }
+
+ /**
+ * Get the system timezone for display purposes.
+ * Laravel uses UTC internally but we display times in server's local timezone.
+ */
+ protected function getSystemTimezone(): string
+ {
+ static $timezone = null;
+ if ($timezone === null) {
+ $timezone = trim(shell_exec('cat /etc/timezone 2>/dev/null') ?? '');
+ if ($timezone === '') {
+ $timezone = trim(shell_exec('timedatectl show -p Timezone --value 2>/dev/null') ?? '');
+ }
+ if ($timezone === '') {
+ $timezone = 'UTC';
+ }
+ }
+
+ return $timezone;
+ }
+}
diff --git a/app/Models/BackupSchedule.php b/app/Models/BackupSchedule.php
index 0dbafb9..81ef79a 100644
--- a/app/Models/BackupSchedule.php
+++ b/app/Models/BackupSchedule.php
@@ -185,51 +185,3 @@ class BackupSchedule extends Model
return $timezone;
}
- /**
- * Scope for active schedules.
- */
- public function scopeActive($query)
- {
- return $query->where('is_active', true);
- }
-
- /**
- * Scope for due schedules.
- */
- public function scopeDue($query)
- {
- return $query->active()
- ->where(function ($q) {
- $q->whereNull('next_run_at')
- ->orWhere('next_run_at', '<=', now());
- });
- }
-
- /**
- * Scope for user schedules.
- */
- public function scopeForUser($query, int $userId)
- {
- return $query->where('user_id', $userId);
- }
-
- /**
- * Scope for server backup schedules.
- */
- public function scopeServerBackups($query)
- {
- return $query->where('is_server_backup', true);
- }
-
- /**
- * Get last status color for UI.
- */
- public function getLastStatusColorAttribute(): string
- {
- return match ($this->last_status) {
- 'success' => 'success',
- 'failed' => 'danger',
- default => 'gray',
- };
- }
-}
diff --git a/doccs/site/.gitignore b/doccs/site/.gitignore
new file mode 100644
index 0000000..de35ccf
--- /dev/null
+++ b/doccs/site/.gitignore
@@ -0,0 +1,4 @@
+node_modules/
+dist/
+.astro/
+.DS_Store
diff --git a/doccs/site/.vscode/extensions.json b/doccs/site/.vscode/extensions.json
new file mode 100644
index 0000000..22a1505
--- /dev/null
+++ b/doccs/site/.vscode/extensions.json
@@ -0,0 +1,4 @@
+{
+ "recommendations": ["astro-build.astro-vscode"],
+ "unwantedRecommendations": []
+}
diff --git a/doccs/site/.vscode/launch.json b/doccs/site/.vscode/launch.json
new file mode 100644
index 0000000..d642209
--- /dev/null
+++ b/doccs/site/.vscode/launch.json
@@ -0,0 +1,11 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "command": "./node_modules/.bin/astro dev",
+ "name": "Development server",
+ "request": "launch",
+ "type": "node-terminal"
+ }
+ ]
+}
diff --git a/doccs/site/README.md b/doccs/site/README.md
new file mode 100644
index 0000000..1b7f5c3
--- /dev/null
+++ b/doccs/site/README.md
@@ -0,0 +1,49 @@
+# Starlight Starter Kit: Basics
+
+[](https://starlight.astro.build)
+
+```
+npm create astro@latest -- --template starlight
+```
+
+> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
+
+## 🚀 Project Structure
+
+Inside of your Astro + Starlight project, you'll see the following folders and files:
+
+```
+.
+├── public/
+├── src/
+│ ├── assets/
+│ ├── content/
+│ │ └── docs/
+│ └── content.config.ts
+├── astro.config.mjs
+├── package.json
+└── tsconfig.json
+```
+
+Starlight looks for `.md` or `.mdx` files in the `src/content/docs/` directory. Each file is exposed as a route based on its file name.
+
+Images can be added to `src/assets/` and embedded in Markdown with a relative link.
+
+Static assets, like favicons, can be placed in the `public/` directory.
+
+## 🧞 Commands
+
+All commands are run from the root of the project, from a terminal:
+
+| Command | Action |
+| :------------------------ | :----------------------------------------------- |
+| `npm install` | Installs dependencies |
+| `npm run dev` | Starts local dev server at `localhost:4321` |
+| `npm run build` | Build your production site to `./dist/` |
+| `npm run preview` | Preview your build locally, before deploying |
+| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
+| `npm run astro -- --help` | Get help using the Astro CLI |
+
+## 👀 Want to learn more?
+
+Check out [Starlight’s docs](https://starlight.astro.build/), read [the Astro documentation](https://docs.astro.build), or jump into the [Astro Discord server](https://astro.build/chat).
diff --git a/doccs/site/astro.config.mjs b/doccs/site/astro.config.mjs
new file mode 100644
index 0000000..3fa76af
--- /dev/null
+++ b/doccs/site/astro.config.mjs
@@ -0,0 +1,34 @@
+// @ts-check
+import { defineConfig } from 'astro/config';
+import starlight from '@astrojs/starlight';
+
+// https://astro.build/config
+export default defineConfig({
+ server: {
+ allowedHosts: ['jabali.lan'],
+ },
+ integrations: [
+ starlight({
+ title: 'Jabali Panel Documentation',
+ description: 'Feature documentation and screenshots for the Jabali hosting panel.',
+ sidebar: [
+ {
+ label: 'Getting Started',
+ items: [{ label: 'Overview', slug: 'overview' }],
+ },
+ {
+ label: 'Admin Panel',
+ autogenerate: { directory: 'admin' },
+ },
+ {
+ label: 'User Panel',
+ autogenerate: { directory: 'user' },
+ },
+ {
+ label: 'Platform',
+ autogenerate: { directory: 'platform' },
+ },
+ ],
+ }),
+ ],
+});
diff --git a/doccs/site/package-lock.json b/doccs/site/package-lock.json
new file mode 100644
index 0000000..41b34af
--- /dev/null
+++ b/doccs/site/package-lock.json
@@ -0,0 +1,6394 @@
+{
+ "name": "doccs-site",
+ "version": "0.0.1",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "doccs-site",
+ "version": "0.0.1",
+ "dependencies": {
+ "@astrojs/starlight": "^0.37.6",
+ "astro": "^5.6.1",
+ "sharp": "^0.34.2"
+ }
+ },
+ "node_modules/@astrojs/compiler": {
+ "version": "2.13.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.13.0.tgz",
+ "integrity": "sha512-mqVORhUJViA28fwHYaWmsXSzLO9osbdZ5ImUfxBarqsYdMlPbqAqGJCxsNzvppp1BEzc1mJNjOVvQqeDN8Vspw==",
+ "license": "MIT"
+ },
+ "node_modules/@astrojs/internal-helpers": {
+ "version": "0.7.5",
+ "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.7.5.tgz",
+ "integrity": "sha512-vreGnYSSKhAjFJCWAwe/CNhONvoc5lokxtRoZims+0wa3KbHBdPHSSthJsKxPd8d/aic6lWKpRTYGY/hsgK6EA==",
+ "license": "MIT"
+ },
+ "node_modules/@astrojs/markdown-remark": {
+ "version": "6.3.10",
+ "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.3.10.tgz",
+ "integrity": "sha512-kk4HeYR6AcnzC4QV8iSlOfh+N8TZ3MEStxPyenyCtemqn8IpEATBFMTJcfrNW32dgpt6MY3oCkMM/Tv3/I4G3A==",
+ "license": "MIT",
+ "dependencies": {
+ "@astrojs/internal-helpers": "0.7.5",
+ "@astrojs/prism": "3.3.0",
+ "github-slugger": "^2.0.0",
+ "hast-util-from-html": "^2.0.3",
+ "hast-util-to-text": "^4.0.2",
+ "import-meta-resolve": "^4.2.0",
+ "js-yaml": "^4.1.1",
+ "mdast-util-definitions": "^6.0.0",
+ "rehype-raw": "^7.0.0",
+ "rehype-stringify": "^10.0.1",
+ "remark-gfm": "^4.0.1",
+ "remark-parse": "^11.0.0",
+ "remark-rehype": "^11.1.2",
+ "remark-smartypants": "^3.0.2",
+ "shiki": "^3.19.0",
+ "smol-toml": "^1.5.2",
+ "unified": "^11.0.5",
+ "unist-util-remove-position": "^5.0.0",
+ "unist-util-visit": "^5.0.0",
+ "unist-util-visit-parents": "^6.0.2",
+ "vfile": "^6.0.3"
+ }
+ },
+ "node_modules/@astrojs/mdx": {
+ "version": "4.3.13",
+ "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-4.3.13.tgz",
+ "integrity": "sha512-IHDHVKz0JfKBy3//52JSiyWv089b7GVSChIXLrlUOoTLWowG3wr2/8hkaEgEyd/vysvNQvGk+QhysXpJW5ve6Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@astrojs/markdown-remark": "6.3.10",
+ "@mdx-js/mdx": "^3.1.1",
+ "acorn": "^8.15.0",
+ "es-module-lexer": "^1.7.0",
+ "estree-util-visit": "^2.0.0",
+ "hast-util-to-html": "^9.0.5",
+ "piccolore": "^0.1.3",
+ "rehype-raw": "^7.0.0",
+ "remark-gfm": "^4.0.1",
+ "remark-smartypants": "^3.0.2",
+ "source-map": "^0.7.6",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.3"
+ },
+ "engines": {
+ "node": "18.20.8 || ^20.3.0 || >=22.0.0"
+ },
+ "peerDependencies": {
+ "astro": "^5.0.0"
+ }
+ },
+ "node_modules/@astrojs/prism": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-3.3.0.tgz",
+ "integrity": "sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "prismjs": "^1.30.0"
+ },
+ "engines": {
+ "node": "18.20.8 || ^20.3.0 || >=22.0.0"
+ }
+ },
+ "node_modules/@astrojs/sitemap": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.7.0.tgz",
+ "integrity": "sha512-+qxjUrz6Jcgh+D5VE1gKUJTA3pSthuPHe6Ao5JCxok794Lewx8hBFaWHtOnN0ntb2lfOf7gvOi9TefUswQ/ZVA==",
+ "license": "MIT",
+ "dependencies": {
+ "sitemap": "^8.0.2",
+ "stream-replace-string": "^2.0.0",
+ "zod": "^3.25.76"
+ }
+ },
+ "node_modules/@astrojs/starlight": {
+ "version": "0.37.6",
+ "resolved": "https://registry.npmjs.org/@astrojs/starlight/-/starlight-0.37.6.tgz",
+ "integrity": "sha512-wQrKwH431q+8FsLBnNQeG+R36TMtEGxTQ2AuiVpcx9APcazvL3n7wVW8mMmYyxX0POjTnxlcWPkdMGR3Yj1L+w==",
+ "license": "MIT",
+ "dependencies": {
+ "@astrojs/markdown-remark": "^6.3.1",
+ "@astrojs/mdx": "^4.2.3",
+ "@astrojs/sitemap": "^3.3.0",
+ "@pagefind/default-ui": "^1.3.0",
+ "@types/hast": "^3.0.4",
+ "@types/js-yaml": "^4.0.9",
+ "@types/mdast": "^4.0.4",
+ "astro-expressive-code": "^0.41.1",
+ "bcp-47": "^2.1.0",
+ "hast-util-from-html": "^2.0.1",
+ "hast-util-select": "^6.0.2",
+ "hast-util-to-string": "^3.0.0",
+ "hastscript": "^9.0.0",
+ "i18next": "^23.11.5",
+ "js-yaml": "^4.1.0",
+ "klona": "^2.0.6",
+ "magic-string": "^0.30.17",
+ "mdast-util-directive": "^3.0.0",
+ "mdast-util-to-markdown": "^2.1.0",
+ "mdast-util-to-string": "^4.0.0",
+ "pagefind": "^1.3.0",
+ "rehype": "^13.0.1",
+ "rehype-format": "^5.0.0",
+ "remark-directive": "^3.0.0",
+ "ultrahtml": "^1.6.0",
+ "unified": "^11.0.5",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.2"
+ },
+ "peerDependencies": {
+ "astro": "^5.5.0"
+ }
+ },
+ "node_modules/@astrojs/telemetry": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.0.tgz",
+ "integrity": "sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ci-info": "^4.2.0",
+ "debug": "^4.4.0",
+ "dlv": "^1.1.3",
+ "dset": "^3.1.4",
+ "is-docker": "^3.0.0",
+ "is-wsl": "^3.1.0",
+ "which-pm-runs": "^1.1.0"
+ },
+ "engines": {
+ "node": "18.20.8 || ^20.3.0 || >=22.0.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz",
+ "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.0"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
+ "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
+ "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@capsizecss/unpack": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-4.0.0.tgz",
+ "integrity": "sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA==",
+ "license": "MIT",
+ "dependencies": {
+ "fontkitten": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@ctrl/tinycolor": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-4.2.0.tgz",
+ "integrity": "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@emnapi/runtime": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz",
+ "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
+ "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
+ "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
+ "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
+ "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
+ "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
+ "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
+ "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
+ "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
+ "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
+ "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
+ "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
+ "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
+ "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
+ "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
+ "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
+ "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
+ "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
+ "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
+ "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
+ "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
+ "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
+ "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
+ "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@expressive-code/core": {
+ "version": "0.41.6",
+ "resolved": "https://registry.npmjs.org/@expressive-code/core/-/core-0.41.6.tgz",
+ "integrity": "sha512-FvJQP+hG0jWi/FLBSmvHInDqWR7jNANp9PUDjdMqSshHb0y7sxx3vHuoOr6SgXjWw+MGLqorZyPQ0aAlHEok6g==",
+ "license": "MIT",
+ "dependencies": {
+ "@ctrl/tinycolor": "^4.0.4",
+ "hast-util-select": "^6.0.2",
+ "hast-util-to-html": "^9.0.1",
+ "hast-util-to-text": "^4.0.1",
+ "hastscript": "^9.0.0",
+ "postcss": "^8.4.38",
+ "postcss-nested": "^6.0.1",
+ "unist-util-visit": "^5.0.0",
+ "unist-util-visit-parents": "^6.0.1"
+ }
+ },
+ "node_modules/@expressive-code/plugin-frames": {
+ "version": "0.41.6",
+ "resolved": "https://registry.npmjs.org/@expressive-code/plugin-frames/-/plugin-frames-0.41.6.tgz",
+ "integrity": "sha512-d+hkSYXIQot6fmYnOmWAM+7TNWRv/dhfjMsNq+mIZz8Tb4mPHOcgcfZeEM5dV9TDL0ioQNvtcqQNuzA1sRPjxg==",
+ "license": "MIT",
+ "dependencies": {
+ "@expressive-code/core": "^0.41.6"
+ }
+ },
+ "node_modules/@expressive-code/plugin-shiki": {
+ "version": "0.41.6",
+ "resolved": "https://registry.npmjs.org/@expressive-code/plugin-shiki/-/plugin-shiki-0.41.6.tgz",
+ "integrity": "sha512-Y6zmKBmsIUtWTzdefqlzm/h9Zz0Rc4gNdt2GTIH7fhHH2I9+lDYCa27BDwuBhjqcos6uK81Aca9dLUC4wzN+ng==",
+ "license": "MIT",
+ "dependencies": {
+ "@expressive-code/core": "^0.41.6",
+ "shiki": "^3.2.2"
+ }
+ },
+ "node_modules/@expressive-code/plugin-text-markers": {
+ "version": "0.41.6",
+ "resolved": "https://registry.npmjs.org/@expressive-code/plugin-text-markers/-/plugin-text-markers-0.41.6.tgz",
+ "integrity": "sha512-PBFa1wGyYzRExMDzBmAWC6/kdfG1oLn4pLpBeTfIRrALPjcGA/59HP3e7q9J0Smk4pC7U+lWkA2LHR8FYV8U7Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@expressive-code/core": "^0.41.6"
+ }
+ },
+ "node_modules/@img/colour": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz",
+ "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@img/sharp-darwin-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",
+ "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-arm64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-darwin-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",
+ "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-x64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
+ "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",
+ "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",
+ "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",
+ "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-ppc64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz",
+ "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-riscv64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz",
+ "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-s390x": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz",
+ "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz",
+ "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",
+ "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz",
+ "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",
+ "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",
+ "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-ppc64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz",
+ "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-ppc64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-riscv64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz",
+ "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-riscv64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-s390x": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz",
+ "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-s390x": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz",
+ "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-x64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",
+ "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz",
+ "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-wasm32": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz",
+ "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==",
+ "cpu": [
+ "wasm32"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/runtime": "^1.7.0"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz",
+ "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-ia32": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz",
+ "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",
+ "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "license": "MIT"
+ },
+ "node_modules/@mdx-js/mdx": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.1.tgz",
+ "integrity": "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "@types/mdx": "^2.0.0",
+ "acorn": "^8.0.0",
+ "collapse-white-space": "^2.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-is-identifier-name": "^3.0.0",
+ "estree-util-scope": "^1.0.0",
+ "estree-walker": "^3.0.0",
+ "hast-util-to-jsx-runtime": "^2.0.0",
+ "markdown-extensions": "^2.0.0",
+ "recma-build-jsx": "^1.0.0",
+ "recma-jsx": "^1.0.0",
+ "recma-stringify": "^1.0.0",
+ "rehype-recma": "^1.0.0",
+ "remark-mdx": "^3.0.0",
+ "remark-parse": "^11.0.0",
+ "remark-rehype": "^11.0.0",
+ "source-map": "^0.7.0",
+ "unified": "^11.0.0",
+ "unist-util-position-from-estree": "^2.0.0",
+ "unist-util-stringify-position": "^4.0.0",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/@oslojs/encoding": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz",
+ "integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==",
+ "license": "MIT"
+ },
+ "node_modules/@pagefind/darwin-arm64": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@pagefind/darwin-arm64/-/darwin-arm64-1.4.0.tgz",
+ "integrity": "sha512-2vMqkbv3lbx1Awea90gTaBsvpzgRs7MuSgKDxW0m9oV1GPZCZbZBJg/qL83GIUEN2BFlY46dtUZi54pwH+/pTQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@pagefind/darwin-x64": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@pagefind/darwin-x64/-/darwin-x64-1.4.0.tgz",
+ "integrity": "sha512-e7JPIS6L9/cJfow+/IAqknsGqEPjJnVXGjpGm25bnq+NPdoD3c/7fAwr1OXkG4Ocjx6ZGSCijXEV4ryMcH2E3A==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@pagefind/default-ui": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@pagefind/default-ui/-/default-ui-1.4.0.tgz",
+ "integrity": "sha512-wie82VWn3cnGEdIjh4YwNESyS1G6vRHwL6cNjy9CFgNnWW/PGRjsLq300xjVH5sfPFK3iK36UxvIBymtQIEiSQ==",
+ "license": "MIT"
+ },
+ "node_modules/@pagefind/freebsd-x64": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@pagefind/freebsd-x64/-/freebsd-x64-1.4.0.tgz",
+ "integrity": "sha512-WcJVypXSZ+9HpiqZjFXMUobfFfZZ6NzIYtkhQ9eOhZrQpeY5uQFqNWLCk7w9RkMUwBv1HAMDW3YJQl/8OqsV0Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@pagefind/linux-arm64": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@pagefind/linux-arm64/-/linux-arm64-1.4.0.tgz",
+ "integrity": "sha512-PIt8dkqt4W06KGmQjONw7EZbhDF+uXI7i0XtRLN1vjCUxM9vGPdtJc2mUyVPevjomrGz5M86M8bqTr6cgDp1Uw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@pagefind/linux-x64": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@pagefind/linux-x64/-/linux-x64-1.4.0.tgz",
+ "integrity": "sha512-z4oddcWwQ0UHrTHR8psLnVlz6USGJ/eOlDPTDYZ4cI8TK8PgwRUPQZp9D2iJPNIPcS6Qx/E4TebjuGJOyK8Mmg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@pagefind/windows-x64": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@pagefind/windows-x64/-/windows-x64-1.4.0.tgz",
+ "integrity": "sha512-NkT+YAdgS2FPCn8mIA9bQhiBs+xmniMGq1LFPDhcFn0+2yIUEiIG06t7bsZlhdjknEQRTSdT7YitP6fC5qwP0g==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/pluginutils": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz",
+ "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "estree-walker": "^2.0.2",
+ "picomatch": "^4.0.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rollup/pluginutils/node_modules/estree-walker": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+ "license": "MIT"
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz",
+ "integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz",
+ "integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz",
+ "integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz",
+ "integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz",
+ "integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz",
+ "integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz",
+ "integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz",
+ "integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz",
+ "integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz",
+ "integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz",
+ "integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz",
+ "integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz",
+ "integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz",
+ "integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz",
+ "integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz",
+ "integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz",
+ "integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz",
+ "integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz",
+ "integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-openbsd-x64": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz",
+ "integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-openharmony-arm64": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz",
+ "integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz",
+ "integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz",
+ "integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz",
+ "integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz",
+ "integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@shikijs/core": {
+ "version": "3.22.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.22.0.tgz",
+ "integrity": "sha512-iAlTtSDDbJiRpvgL5ugKEATDtHdUVkqgHDm/gbD2ZS9c88mx7G1zSYjjOxp5Qa0eaW0MAQosFRmJSk354PRoQA==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.22.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4",
+ "hast-util-to-html": "^9.0.5"
+ }
+ },
+ "node_modules/@shikijs/engine-javascript": {
+ "version": "3.22.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.22.0.tgz",
+ "integrity": "sha512-jdKhfgW9CRtj3Tor0L7+yPwdG3CgP7W+ZEqSsojrMzCjD1e0IxIbwUMDDpYlVBlC08TACg4puwFGkZfLS+56Tw==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.22.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "oniguruma-to-es": "^4.3.4"
+ }
+ },
+ "node_modules/@shikijs/engine-oniguruma": {
+ "version": "3.22.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.22.0.tgz",
+ "integrity": "sha512-DyXsOG0vGtNtl7ygvabHd7Mt5EY8gCNqR9Y7Lpbbd/PbJvgWrqaKzH1JW6H6qFkuUa8aCxoiYVv8/YfFljiQxA==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.22.0",
+ "@shikijs/vscode-textmate": "^10.0.2"
+ }
+ },
+ "node_modules/@shikijs/langs": {
+ "version": "3.22.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.22.0.tgz",
+ "integrity": "sha512-x/42TfhWmp6H00T6uwVrdTJGKgNdFbrEdhaDwSR5fd5zhQ1Q46bHq9EO61SCEWJR0HY7z2HNDMaBZp8JRmKiIA==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.22.0"
+ }
+ },
+ "node_modules/@shikijs/themes": {
+ "version": "3.22.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.22.0.tgz",
+ "integrity": "sha512-o+tlOKqsr6FE4+mYJG08tfCFDS+3CG20HbldXeVoyP+cYSUxDhrFf3GPjE60U55iOkkjbpY2uC3It/eeja35/g==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.22.0"
+ }
+ },
+ "node_modules/@shikijs/types": {
+ "version": "3.22.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.22.0.tgz",
+ "integrity": "sha512-491iAekgKDBFE67z70Ok5a8KBMsQ2IJwOWw3us/7ffQkIBCyOQfm/aNwVMBUriP02QshIfgHCBSIYAl3u2eWjg==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4"
+ }
+ },
+ "node_modules/@shikijs/vscode-textmate": {
+ "version": "10.0.2",
+ "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz",
+ "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/debug": {
+ "version": "4.1.12",
+ "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
+ "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/ms": "*"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "license": "MIT"
+ },
+ "node_modules/@types/estree-jsx": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz",
+ "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "*"
+ }
+ },
+ "node_modules/@types/hast": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
+ "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
+ "node_modules/@types/js-yaml": {
+ "version": "4.0.9",
+ "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz",
+ "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/mdast": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
+ "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
+ "node_modules/@types/mdx": {
+ "version": "2.0.13",
+ "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz",
+ "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/ms": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
+ "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/nlcst": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/nlcst/-/nlcst-2.0.3.tgz",
+ "integrity": "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "25.2.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.0.tgz",
+ "integrity": "sha512-DZ8VwRFUNzuqJ5khrvwMXHmvPe+zGayJhr2CDNiKB1WBE1ST8Djl00D0IC4vvNmHMdj6DlbYRIaFE7WHjlDl5w==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~7.16.0"
+ }
+ },
+ "node_modules/@types/sax": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz",
+ "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/unist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
+ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
+ "license": "MIT"
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
+ "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
+ "license": "ISC"
+ },
+ "node_modules/acorn": {
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ansi-align": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
+ "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.1.0"
+ }
+ },
+ "node_modules/ansi-align/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-align/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/ansi-align/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-align/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
+ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
+ "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/anymatch/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/arg": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
+ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
+ "license": "MIT"
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "license": "Python-2.0"
+ },
+ "node_modules/aria-query": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
+ "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/array-iterate": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-2.0.1.tgz",
+ "integrity": "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/astring": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz",
+ "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==",
+ "license": "MIT",
+ "bin": {
+ "astring": "bin/astring"
+ }
+ },
+ "node_modules/astro": {
+ "version": "5.17.1",
+ "resolved": "https://registry.npmjs.org/astro/-/astro-5.17.1.tgz",
+ "integrity": "sha512-oD3tlxTaVWGq/Wfbqk6gxzVRz98xa/rYlpe+gU2jXJMSD01k6sEDL01ZlT8mVSYB/rMgnvIOfiQQ3BbLdN237A==",
+ "license": "MIT",
+ "dependencies": {
+ "@astrojs/compiler": "^2.13.0",
+ "@astrojs/internal-helpers": "0.7.5",
+ "@astrojs/markdown-remark": "6.3.10",
+ "@astrojs/telemetry": "3.3.0",
+ "@capsizecss/unpack": "^4.0.0",
+ "@oslojs/encoding": "^1.1.0",
+ "@rollup/pluginutils": "^5.3.0",
+ "acorn": "^8.15.0",
+ "aria-query": "^5.3.2",
+ "axobject-query": "^4.1.0",
+ "boxen": "8.0.1",
+ "ci-info": "^4.3.1",
+ "clsx": "^2.1.1",
+ "common-ancestor-path": "^1.0.1",
+ "cookie": "^1.1.1",
+ "cssesc": "^3.0.0",
+ "debug": "^4.4.3",
+ "deterministic-object-hash": "^2.0.2",
+ "devalue": "^5.6.2",
+ "diff": "^8.0.3",
+ "dlv": "^1.1.3",
+ "dset": "^3.1.4",
+ "es-module-lexer": "^1.7.0",
+ "esbuild": "^0.25.0",
+ "estree-walker": "^3.0.3",
+ "flattie": "^1.1.1",
+ "fontace": "~0.4.0",
+ "github-slugger": "^2.0.0",
+ "html-escaper": "3.0.3",
+ "http-cache-semantics": "^4.2.0",
+ "import-meta-resolve": "^4.2.0",
+ "js-yaml": "^4.1.1",
+ "magic-string": "^0.30.21",
+ "magicast": "^0.5.1",
+ "mrmime": "^2.0.1",
+ "neotraverse": "^0.6.18",
+ "p-limit": "^6.2.0",
+ "p-queue": "^8.1.1",
+ "package-manager-detector": "^1.6.0",
+ "piccolore": "^0.1.3",
+ "picomatch": "^4.0.3",
+ "prompts": "^2.4.2",
+ "rehype": "^13.0.2",
+ "semver": "^7.7.3",
+ "shiki": "^3.21.0",
+ "smol-toml": "^1.6.0",
+ "svgo": "^4.0.0",
+ "tinyexec": "^1.0.2",
+ "tinyglobby": "^0.2.15",
+ "tsconfck": "^3.1.6",
+ "ultrahtml": "^1.6.0",
+ "unifont": "~0.7.3",
+ "unist-util-visit": "^5.0.0",
+ "unstorage": "^1.17.4",
+ "vfile": "^6.0.3",
+ "vite": "^6.4.1",
+ "vitefu": "^1.1.1",
+ "xxhash-wasm": "^1.1.0",
+ "yargs-parser": "^21.1.1",
+ "yocto-spinner": "^0.2.3",
+ "zod": "^3.25.76",
+ "zod-to-json-schema": "^3.25.1",
+ "zod-to-ts": "^1.2.0"
+ },
+ "bin": {
+ "astro": "astro.js"
+ },
+ "engines": {
+ "node": "18.20.8 || ^20.3.0 || >=22.0.0",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/astrodotbuild"
+ },
+ "optionalDependencies": {
+ "sharp": "^0.34.0"
+ }
+ },
+ "node_modules/astro-expressive-code": {
+ "version": "0.41.6",
+ "resolved": "https://registry.npmjs.org/astro-expressive-code/-/astro-expressive-code-0.41.6.tgz",
+ "integrity": "sha512-l47tb1uhmVIebHUkw+HEPtU/av0G4O8Q34g2cbkPvC7/e9ZhANcjUUciKt9Hp6gSVDdIuXBBLwJQn2LkeGMOAw==",
+ "license": "MIT",
+ "dependencies": {
+ "rehype-expressive-code": "^0.41.6"
+ },
+ "peerDependencies": {
+ "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta"
+ }
+ },
+ "node_modules/axobject-query": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
+ "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/bail": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
+ "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/base-64": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz",
+ "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==",
+ "license": "MIT"
+ },
+ "node_modules/bcp-47": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/bcp-47/-/bcp-47-2.1.0.tgz",
+ "integrity": "sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==",
+ "license": "MIT",
+ "dependencies": {
+ "is-alphabetical": "^2.0.0",
+ "is-alphanumerical": "^2.0.0",
+ "is-decimal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/bcp-47-match": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz",
+ "integrity": "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+ "license": "ISC"
+ },
+ "node_modules/boxen": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz",
+ "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-align": "^3.0.1",
+ "camelcase": "^8.0.0",
+ "chalk": "^5.3.0",
+ "cli-boxes": "^3.0.0",
+ "string-width": "^7.2.0",
+ "type-fest": "^4.21.0",
+ "widest-line": "^5.0.0",
+ "wrap-ansi": "^9.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz",
+ "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ccount": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
+ "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
+ "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
+ "license": "MIT",
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/character-entities": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz",
+ "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-html4": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
+ "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-legacy": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz",
+ "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-reference-invalid": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz",
+ "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz",
+ "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==",
+ "license": "MIT",
+ "dependencies": {
+ "readdirp": "^5.0.0"
+ },
+ "engines": {
+ "node": ">= 20.19.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz",
+ "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cli-boxes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz",
+ "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/collapse-white-space": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz",
+ "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/comma-separated-tokens": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
+ "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/commander": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
+ "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/common-ancestor-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz",
+ "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==",
+ "license": "ISC"
+ },
+ "node_modules/cookie": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
+ "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/cookie-es": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.2.tgz",
+ "integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==",
+ "license": "MIT"
+ },
+ "node_modules/crossws": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz",
+ "integrity": "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==",
+ "license": "MIT",
+ "dependencies": {
+ "uncrypto": "^0.1.3"
+ }
+ },
+ "node_modules/css-select": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz",
+ "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-what": "^6.1.0",
+ "domhandler": "^5.0.2",
+ "domutils": "^3.0.1",
+ "nth-check": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/css-selector-parser": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-3.3.0.tgz",
+ "integrity": "sha512-Y2asgMGFqJKF4fq4xHDSlFYIkeVfRsm69lQC1q9kbEsH5XtnINTMrweLkjYMeaUgiXBy/uvKeO/a1JHTNnmB2g==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/mdevils"
+ },
+ {
+ "type": "patreon",
+ "url": "https://patreon.com/mdevils"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/css-tree": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz",
+ "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==",
+ "license": "MIT",
+ "dependencies": {
+ "mdn-data": "2.12.2",
+ "source-map-js": "^1.0.1"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
+ }
+ },
+ "node_modules/css-what": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
+ "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "license": "MIT",
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/csso": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz",
+ "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==",
+ "license": "MIT",
+ "dependencies": {
+ "css-tree": "~2.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
+ "npm": ">=7.0.0"
+ }
+ },
+ "node_modules/csso/node_modules/css-tree": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz",
+ "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==",
+ "license": "MIT",
+ "dependencies": {
+ "mdn-data": "2.0.28",
+ "source-map-js": "^1.0.1"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
+ "npm": ">=7.0.0"
+ }
+ },
+ "node_modules/csso/node_modules/mdn-data": {
+ "version": "2.0.28",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz",
+ "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==",
+ "license": "CC0-1.0"
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decode-named-character-reference": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz",
+ "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==",
+ "license": "MIT",
+ "dependencies": {
+ "character-entities": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/defu": {
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
+ "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
+ "license": "MIT"
+ },
+ "node_modules/dequal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/destr": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz",
+ "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==",
+ "license": "MIT"
+ },
+ "node_modules/detect-libc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/deterministic-object-hash": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/deterministic-object-hash/-/deterministic-object-hash-2.0.2.tgz",
+ "integrity": "sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==",
+ "license": "MIT",
+ "dependencies": {
+ "base-64": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/devalue": {
+ "version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.2.tgz",
+ "integrity": "sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg==",
+ "license": "MIT"
+ },
+ "node_modules/devlop": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
+ "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==",
+ "license": "MIT",
+ "dependencies": {
+ "dequal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/diff": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz",
+ "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/direction": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/direction/-/direction-2.0.1.tgz",
+ "integrity": "sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==",
+ "license": "MIT",
+ "bin": {
+ "direction": "cli.js"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/dlv": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
+ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
+ "license": "MIT"
+ },
+ "node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/dom-serializer/node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/domutils": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
+ "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/dset": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz",
+ "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "10.6.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz",
+ "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==",
+ "license": "MIT"
+ },
+ "node_modules/entities": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
+ "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/es-module-lexer": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
+ "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
+ "license": "MIT"
+ },
+ "node_modules/esast-util-from-estree": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz",
+ "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-visit": "^2.0.0",
+ "unist-util-position-from-estree": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/esast-util-from-js": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz",
+ "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "acorn": "^8.0.0",
+ "esast-util-from-estree": "^2.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
+ "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.25.12",
+ "@esbuild/android-arm": "0.25.12",
+ "@esbuild/android-arm64": "0.25.12",
+ "@esbuild/android-x64": "0.25.12",
+ "@esbuild/darwin-arm64": "0.25.12",
+ "@esbuild/darwin-x64": "0.25.12",
+ "@esbuild/freebsd-arm64": "0.25.12",
+ "@esbuild/freebsd-x64": "0.25.12",
+ "@esbuild/linux-arm": "0.25.12",
+ "@esbuild/linux-arm64": "0.25.12",
+ "@esbuild/linux-ia32": "0.25.12",
+ "@esbuild/linux-loong64": "0.25.12",
+ "@esbuild/linux-mips64el": "0.25.12",
+ "@esbuild/linux-ppc64": "0.25.12",
+ "@esbuild/linux-riscv64": "0.25.12",
+ "@esbuild/linux-s390x": "0.25.12",
+ "@esbuild/linux-x64": "0.25.12",
+ "@esbuild/netbsd-arm64": "0.25.12",
+ "@esbuild/netbsd-x64": "0.25.12",
+ "@esbuild/openbsd-arm64": "0.25.12",
+ "@esbuild/openbsd-x64": "0.25.12",
+ "@esbuild/openharmony-arm64": "0.25.12",
+ "@esbuild/sunos-x64": "0.25.12",
+ "@esbuild/win32-arm64": "0.25.12",
+ "@esbuild/win32-ia32": "0.25.12",
+ "@esbuild/win32-x64": "0.25.12"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
+ "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/estree-util-attach-comments": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz",
+ "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/estree-util-build-jsx": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz",
+ "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-is-identifier-name": "^3.0.0",
+ "estree-walker": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/estree-util-is-identifier-name": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz",
+ "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/estree-util-scope": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.0.tgz",
+ "integrity": "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "devlop": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/estree-util-to-js": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz",
+ "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "astring": "^1.8.0",
+ "source-map": "^0.7.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/estree-util-visit": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz",
+ "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/estree-walker": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
+ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0"
+ }
+ },
+ "node_modules/eventemitter3": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz",
+ "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==",
+ "license": "MIT"
+ },
+ "node_modules/expressive-code": {
+ "version": "0.41.6",
+ "resolved": "https://registry.npmjs.org/expressive-code/-/expressive-code-0.41.6.tgz",
+ "integrity": "sha512-W/5+IQbrpCIM5KGLjO35wlp1NCwDOOVQb+PAvzEoGkW1xjGM807ZGfBKptNWH6UECvt6qgmLyWolCMYKh7eQmA==",
+ "license": "MIT",
+ "dependencies": {
+ "@expressive-code/core": "^0.41.6",
+ "@expressive-code/plugin-frames": "^0.41.6",
+ "@expressive-code/plugin-shiki": "^0.41.6",
+ "@expressive-code/plugin-text-markers": "^0.41.6"
+ }
+ },
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "license": "MIT"
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/flattie": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz",
+ "integrity": "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/fontace": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.4.1.tgz",
+ "integrity": "sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw==",
+ "license": "MIT",
+ "dependencies": {
+ "fontkitten": "^1.0.2"
+ }
+ },
+ "node_modules/fontkitten": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/fontkitten/-/fontkitten-1.0.2.tgz",
+ "integrity": "sha512-piJxbLnkD9Xcyi7dWJRnqszEURixe7CrF/efBfbffe2DPyabmuIuqraruY8cXTs19QoM8VJzx47BDRVNXETM7Q==",
+ "license": "MIT",
+ "dependencies": {
+ "tiny-inflate": "^1.0.3"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/get-east-asian-width": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz",
+ "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/github-slugger": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz",
+ "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==",
+ "license": "ISC"
+ },
+ "node_modules/h3": {
+ "version": "1.15.5",
+ "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.5.tgz",
+ "integrity": "sha512-xEyq3rSl+dhGX2Lm0+eFQIAzlDN6Fs0EcC4f7BNUmzaRX/PTzeuM+Tr2lHB8FoXggsQIeXLj8EDVgs5ywxyxmg==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie-es": "^1.2.2",
+ "crossws": "^0.3.5",
+ "defu": "^6.1.4",
+ "destr": "^2.0.5",
+ "iron-webcrypto": "^1.2.1",
+ "node-mock-http": "^1.0.4",
+ "radix3": "^1.1.2",
+ "ufo": "^1.6.3",
+ "uncrypto": "^0.1.3"
+ }
+ },
+ "node_modules/hast-util-embedded": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-embedded/-/hast-util-embedded-3.0.0.tgz",
+ "integrity": "sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hast-util-is-element": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-format": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/hast-util-format/-/hast-util-format-1.1.0.tgz",
+ "integrity": "sha512-yY1UDz6bC9rDvCWHpx12aIBGRG7krurX0p0Fm6pT547LwDIZZiNr8a+IHDogorAdreULSEzP82Nlv5SZkHZcjA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hast-util-embedded": "^3.0.0",
+ "hast-util-minify-whitespace": "^1.0.0",
+ "hast-util-phrasing": "^3.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "html-whitespace-sensitive-tag-names": "^3.0.0",
+ "unist-util-visit-parents": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-from-html": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz",
+ "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "devlop": "^1.1.0",
+ "hast-util-from-parse5": "^8.0.0",
+ "parse5": "^7.0.0",
+ "vfile": "^6.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-from-parse5": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz",
+ "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "devlop": "^1.0.0",
+ "hastscript": "^9.0.0",
+ "property-information": "^7.0.0",
+ "vfile": "^6.0.0",
+ "vfile-location": "^5.0.0",
+ "web-namespaces": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-has-property": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-3.0.0.tgz",
+ "integrity": "sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-is-body-ok-link": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/hast-util-is-body-ok-link/-/hast-util-is-body-ok-link-3.0.1.tgz",
+ "integrity": "sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-is-element": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz",
+ "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-minify-whitespace": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hast-util-minify-whitespace/-/hast-util-minify-whitespace-1.0.1.tgz",
+ "integrity": "sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hast-util-embedded": "^3.0.0",
+ "hast-util-is-element": "^3.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "unist-util-is": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-parse-selector": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz",
+ "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-phrasing": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/hast-util-phrasing/-/hast-util-phrasing-3.0.1.tgz",
+ "integrity": "sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hast-util-embedded": "^3.0.0",
+ "hast-util-has-property": "^3.0.0",
+ "hast-util-is-body-ok-link": "^3.0.0",
+ "hast-util-is-element": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-raw": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz",
+ "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "@ungap/structured-clone": "^1.0.0",
+ "hast-util-from-parse5": "^8.0.0",
+ "hast-util-to-parse5": "^8.0.0",
+ "html-void-elements": "^3.0.0",
+ "mdast-util-to-hast": "^13.0.0",
+ "parse5": "^7.0.0",
+ "unist-util-position": "^5.0.0",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.0",
+ "web-namespaces": "^2.0.0",
+ "zwitch": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-select": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-6.0.4.tgz",
+ "integrity": "sha512-RqGS1ZgI0MwxLaKLDxjprynNzINEkRHY2i8ln4DDjgv9ZhcYVIHN9rlpiYsqtFwrgpYU361SyWDQcGNIBVu3lw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "bcp-47-match": "^2.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "css-selector-parser": "^3.0.0",
+ "devlop": "^1.0.0",
+ "direction": "^2.0.0",
+ "hast-util-has-property": "^3.0.0",
+ "hast-util-to-string": "^3.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "nth-check": "^2.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "unist-util-visit": "^5.0.0",
+ "zwitch": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-to-estree": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz",
+ "integrity": "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-attach-comments": "^3.0.0",
+ "estree-util-is-identifier-name": "^3.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "mdast-util-mdx-expression": "^2.0.0",
+ "mdast-util-mdx-jsx": "^3.0.0",
+ "mdast-util-mdxjs-esm": "^2.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "style-to-js": "^1.0.0",
+ "unist-util-position": "^5.0.0",
+ "zwitch": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-to-html": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz",
+ "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "ccount": "^2.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "html-void-elements": "^3.0.0",
+ "mdast-util-to-hast": "^13.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "stringify-entities": "^4.0.0",
+ "zwitch": "^2.0.4"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-to-jsx-runtime": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz",
+ "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-is-identifier-name": "^3.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "mdast-util-mdx-expression": "^2.0.0",
+ "mdast-util-mdx-jsx": "^3.0.0",
+ "mdast-util-mdxjs-esm": "^2.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "style-to-js": "^1.0.0",
+ "unist-util-position": "^5.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-to-parse5": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.1.tgz",
+ "integrity": "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "devlop": "^1.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "web-namespaces": "^2.0.0",
+ "zwitch": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-to-string": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz",
+ "integrity": "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-to-text": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz",
+ "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "hast-util-is-element": "^3.0.0",
+ "unist-util-find-after": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-whitespace": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz",
+ "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hastscript": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz",
+ "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "hast-util-parse-selector": "^4.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/html-escaper": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz",
+ "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==",
+ "license": "MIT"
+ },
+ "node_modules/html-void-elements": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz",
+ "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/html-whitespace-sensitive-tag-names": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/html-whitespace-sensitive-tag-names/-/html-whitespace-sensitive-tag-names-3.0.1.tgz",
+ "integrity": "sha512-q+310vW8zmymYHALr1da4HyXUQ0zgiIwIicEfotYPWGN0OJVEN/58IJ3A4GBYcEq3LGAZqKb+ugvP0GNB9CEAA==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/http-cache-semantics": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
+ "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/i18next": {
+ "version": "23.16.8",
+ "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.8.tgz",
+ "integrity": "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://locize.com"
+ },
+ {
+ "type": "individual",
+ "url": "https://locize.com/i18next.html"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.23.2"
+ }
+ },
+ "node_modules/import-meta-resolve": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz",
+ "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/inline-style-parser": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz",
+ "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==",
+ "license": "MIT"
+ },
+ "node_modules/iron-webcrypto": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz",
+ "integrity": "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/brc-dd"
+ }
+ },
+ "node_modules/is-alphabetical": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
+ "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-alphanumerical": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz",
+ "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==",
+ "license": "MIT",
+ "dependencies": {
+ "is-alphabetical": "^2.0.0",
+ "is-decimal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-decimal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz",
+ "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-docker": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
+ "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
+ "license": "MIT",
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-hexadecimal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz",
+ "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-inside-container": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
+ "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
+ "license": "MIT",
+ "dependencies": {
+ "is-docker": "^3.0.0"
+ },
+ "bin": {
+ "is-inside-container": "cli.js"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
+ "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-wsl": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz",
+ "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==",
+ "license": "MIT",
+ "dependencies": {
+ "is-inside-container": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/klona": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz",
+ "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/longest-streak": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz",
+ "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "11.2.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.5.tgz",
+ "integrity": "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
+ "node_modules/magicast": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.1.tgz",
+ "integrity": "sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.28.5",
+ "@babel/types": "^7.28.5",
+ "source-map-js": "^1.2.1"
+ }
+ },
+ "node_modules/markdown-extensions": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz",
+ "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/markdown-table": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz",
+ "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/mdast-util-definitions": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-6.0.0.tgz",
+ "integrity": "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "@types/unist": "^3.0.0",
+ "unist-util-visit": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-directive": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.1.0.tgz",
+ "integrity": "sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "@types/unist": "^3.0.0",
+ "ccount": "^2.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0",
+ "parse-entities": "^4.0.0",
+ "stringify-entities": "^4.0.0",
+ "unist-util-visit-parents": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-find-and-replace": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz",
+ "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "escape-string-regexp": "^5.0.0",
+ "unist-util-is": "^6.0.0",
+ "unist-util-visit-parents": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-from-markdown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz",
+ "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "@types/unist": "^3.0.0",
+ "decode-named-character-reference": "^1.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-to-string": "^4.0.0",
+ "micromark": "^4.0.0",
+ "micromark-util-decode-numeric-character-reference": "^2.0.0",
+ "micromark-util-decode-string": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "unist-util-stringify-position": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz",
+ "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==",
+ "license": "MIT",
+ "dependencies": {
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-gfm-autolink-literal": "^2.0.0",
+ "mdast-util-gfm-footnote": "^2.0.0",
+ "mdast-util-gfm-strikethrough": "^2.0.0",
+ "mdast-util-gfm-table": "^2.0.0",
+ "mdast-util-gfm-task-list-item": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm-autolink-literal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz",
+ "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "ccount": "^2.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-find-and-replace": "^3.0.0",
+ "micromark-util-character": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm-footnote": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz",
+ "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.1.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm-strikethrough": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz",
+ "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm-table": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz",
+ "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.0.0",
+ "markdown-table": "^3.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm-task-list-item": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz",
+ "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-mdx": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz",
+ "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==",
+ "license": "MIT",
+ "dependencies": {
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-mdx-expression": "^2.0.0",
+ "mdast-util-mdx-jsx": "^3.0.0",
+ "mdast-util-mdxjs-esm": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-mdx-expression": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz",
+ "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-mdx-jsx": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz",
+ "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "@types/unist": "^3.0.0",
+ "ccount": "^2.0.0",
+ "devlop": "^1.1.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0",
+ "parse-entities": "^4.0.0",
+ "stringify-entities": "^4.0.0",
+ "unist-util-stringify-position": "^4.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-mdxjs-esm": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz",
+ "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-phrasing": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz",
+ "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "unist-util-is": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-to-hast": {
+ "version": "13.2.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz",
+ "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "@ungap/structured-clone": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "trim-lines": "^3.0.0",
+ "unist-util-position": "^5.0.0",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-to-markdown": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz",
+ "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "@types/unist": "^3.0.0",
+ "longest-streak": "^3.0.0",
+ "mdast-util-phrasing": "^4.0.0",
+ "mdast-util-to-string": "^4.0.0",
+ "micromark-util-classify-character": "^2.0.0",
+ "micromark-util-decode-string": "^2.0.0",
+ "unist-util-visit": "^5.0.0",
+ "zwitch": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-to-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz",
+ "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdn-data": {
+ "version": "2.12.2",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz",
+ "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==",
+ "license": "CC0-1.0"
+ },
+ "node_modules/micromark": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz",
+ "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@types/debug": "^4.0.0",
+ "debug": "^4.0.0",
+ "decode-named-character-reference": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-core-commonmark": "^2.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-combine-extensions": "^2.0.0",
+ "micromark-util-decode-numeric-character-reference": "^2.0.0",
+ "micromark-util-encode": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0",
+ "micromark-util-resolve-all": "^2.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "micromark-util-subtokenize": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-core-commonmark": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz",
+ "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "decode-named-character-reference": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-factory-destination": "^2.0.0",
+ "micromark-factory-label": "^2.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-factory-title": "^2.0.0",
+ "micromark-factory-whitespace": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-classify-character": "^2.0.0",
+ "micromark-util-html-tag-name": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0",
+ "micromark-util-resolve-all": "^2.0.0",
+ "micromark-util-subtokenize": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-extension-directive": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.2.tgz",
+ "integrity": "sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==",
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-factory-whitespace": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "parse-entities": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz",
+ "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==",
+ "license": "MIT",
+ "dependencies": {
+ "micromark-extension-gfm-autolink-literal": "^2.0.0",
+ "micromark-extension-gfm-footnote": "^2.0.0",
+ "micromark-extension-gfm-strikethrough": "^2.0.0",
+ "micromark-extension-gfm-table": "^2.0.0",
+ "micromark-extension-gfm-tagfilter": "^2.0.0",
+ "micromark-extension-gfm-task-list-item": "^2.0.0",
+ "micromark-util-combine-extensions": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-autolink-literal": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz",
+ "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==",
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-footnote": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz",
+ "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==",
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-core-commonmark": "^2.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-strikethrough": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz",
+ "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==",
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-classify-character": "^2.0.0",
+ "micromark-util-resolve-all": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-table": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz",
+ "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==",
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-tagfilter": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz",
+ "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==",
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-task-list-item": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz",
+ "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==",
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-mdx-expression": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz",
+ "integrity": "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-factory-mdx-expression": "^2.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-events-to-acorn": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-extension-mdx-jsx": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz",
+ "integrity": "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-is-identifier-name": "^3.0.0",
+ "micromark-factory-mdx-expression": "^2.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-events-to-acorn": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-mdx-md": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz",
+ "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-mdxjs": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz",
+ "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==",
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.0.0",
+ "acorn-jsx": "^5.0.0",
+ "micromark-extension-mdx-expression": "^3.0.0",
+ "micromark-extension-mdx-jsx": "^3.0.0",
+ "micromark-extension-mdx-md": "^2.0.0",
+ "micromark-extension-mdxjs-esm": "^3.0.0",
+ "micromark-util-combine-extensions": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-mdxjs-esm": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz",
+ "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-core-commonmark": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-events-to-acorn": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "unist-util-position-from-estree": "^2.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-factory-destination": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz",
+ "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-factory-label": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz",
+ "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-factory-mdx-expression": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz",
+ "integrity": "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-events-to-acorn": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "unist-util-position-from-estree": "^2.0.0",
+ "vfile-message": "^4.0.0"
+ }
+ },
+ "node_modules/micromark-factory-space": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz",
+ "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-factory-title": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz",
+ "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-factory-whitespace": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz",
+ "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-character": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz",
+ "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-chunked": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz",
+ "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-classify-character": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz",
+ "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-combine-extensions": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz",
+ "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-decode-numeric-character-reference": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz",
+ "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-decode-string": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz",
+ "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "decode-named-character-reference": "^1.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-decode-numeric-character-reference": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-encode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz",
+ "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-events-to-acorn": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz",
+ "integrity": "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "@types/unist": "^3.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-visit": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "vfile-message": "^4.0.0"
+ }
+ },
+ "node_modules/micromark-util-html-tag-name": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz",
+ "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-normalize-identifier": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz",
+ "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-resolve-all": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz",
+ "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-sanitize-uri": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz",
+ "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-encode": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-subtokenize": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz",
+ "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-symbol": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz",
+ "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-types": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz",
+ "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/mrmime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
+ "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/neotraverse": {
+ "version": "0.6.18",
+ "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.18.tgz",
+ "integrity": "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/nlcst-to-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz",
+ "integrity": "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/nlcst": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/node-fetch-native": {
+ "version": "1.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz",
+ "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==",
+ "license": "MIT"
+ },
+ "node_modules/node-mock-http": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.4.tgz",
+ "integrity": "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==",
+ "license": "MIT"
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/nth-check": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/nth-check?sponsor=1"
+ }
+ },
+ "node_modules/ofetch": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz",
+ "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==",
+ "license": "MIT",
+ "dependencies": {
+ "destr": "^2.0.5",
+ "node-fetch-native": "^1.6.7",
+ "ufo": "^1.6.1"
+ }
+ },
+ "node_modules/ohash": {
+ "version": "2.0.11",
+ "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz",
+ "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==",
+ "license": "MIT"
+ },
+ "node_modules/oniguruma-parser": {
+ "version": "0.12.1",
+ "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz",
+ "integrity": "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==",
+ "license": "MIT"
+ },
+ "node_modules/oniguruma-to-es": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.4.tgz",
+ "integrity": "sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA==",
+ "license": "MIT",
+ "dependencies": {
+ "oniguruma-parser": "^0.12.1",
+ "regex": "^6.0.1",
+ "regex-recursion": "^6.0.2"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.2.0.tgz",
+ "integrity": "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==",
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-queue": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.1.tgz",
+ "integrity": "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==",
+ "license": "MIT",
+ "dependencies": {
+ "eventemitter3": "^5.0.1",
+ "p-timeout": "^6.1.2"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-timeout": {
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.4.tgz",
+ "integrity": "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/package-manager-detector": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz",
+ "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==",
+ "license": "MIT"
+ },
+ "node_modules/pagefind": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/pagefind/-/pagefind-1.4.0.tgz",
+ "integrity": "sha512-z2kY1mQlL4J8q5EIsQkLzQjilovKzfNVhX8De6oyE6uHpfFtyBaqUpcl/XzJC/4fjD8vBDyh1zolimIcVrCn9g==",
+ "license": "MIT",
+ "bin": {
+ "pagefind": "lib/runner/bin.cjs"
+ },
+ "optionalDependencies": {
+ "@pagefind/darwin-arm64": "1.4.0",
+ "@pagefind/darwin-x64": "1.4.0",
+ "@pagefind/freebsd-x64": "1.4.0",
+ "@pagefind/linux-arm64": "1.4.0",
+ "@pagefind/linux-x64": "1.4.0",
+ "@pagefind/windows-x64": "1.4.0"
+ }
+ },
+ "node_modules/parse-entities": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz",
+ "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "character-entities-legacy": "^3.0.0",
+ "character-reference-invalid": "^2.0.0",
+ "decode-named-character-reference": "^1.0.0",
+ "is-alphanumerical": "^2.0.0",
+ "is-decimal": "^2.0.0",
+ "is-hexadecimal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/parse-entities/node_modules/@types/unist": {
+ "version": "2.0.11",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
+ "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
+ "license": "MIT"
+ },
+ "node_modules/parse-latin": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz",
+ "integrity": "sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/nlcst": "^2.0.0",
+ "@types/unist": "^3.0.0",
+ "nlcst-to-string": "^4.0.0",
+ "unist-util-modify-children": "^4.0.0",
+ "unist-util-visit-children": "^3.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/parse5": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
+ "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
+ "license": "MIT",
+ "dependencies": {
+ "entities": "^6.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/piccolore": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/piccolore/-/piccolore-0.1.3.tgz",
+ "integrity": "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==",
+ "license": "ISC"
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.6",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
+ "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-nested": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
+ "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "postcss-selector-parser": "^6.1.1"
+ },
+ "engines": {
+ "node": ">=12.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.14"
+ }
+ },
+ "node_modules/postcss-selector-parser": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+ "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
+ "license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/prismjs": {
+ "version": "1.30.0",
+ "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
+ "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "license": "MIT",
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/property-information": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz",
+ "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/radix3": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz",
+ "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==",
+ "license": "MIT"
+ },
+ "node_modules/readdirp": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz",
+ "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20.19.0"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/recma-build-jsx": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz",
+ "integrity": "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "estree-util-build-jsx": "^3.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/recma-jsx": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.1.tgz",
+ "integrity": "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==",
+ "license": "MIT",
+ "dependencies": {
+ "acorn-jsx": "^5.0.0",
+ "estree-util-to-js": "^2.0.0",
+ "recma-parse": "^1.0.0",
+ "recma-stringify": "^1.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ },
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/recma-parse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz",
+ "integrity": "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "esast-util-from-js": "^2.0.0",
+ "unified": "^11.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/recma-stringify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz",
+ "integrity": "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "estree-util-to-js": "^2.0.0",
+ "unified": "^11.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz",
+ "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==",
+ "license": "MIT",
+ "dependencies": {
+ "regex-utilities": "^2.3.0"
+ }
+ },
+ "node_modules/regex-recursion": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz",
+ "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==",
+ "license": "MIT",
+ "dependencies": {
+ "regex-utilities": "^2.3.0"
+ }
+ },
+ "node_modules/regex-utilities": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz",
+ "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==",
+ "license": "MIT"
+ },
+ "node_modules/rehype": {
+ "version": "13.0.2",
+ "resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.2.tgz",
+ "integrity": "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "rehype-parse": "^9.0.0",
+ "rehype-stringify": "^10.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/rehype-expressive-code": {
+ "version": "0.41.6",
+ "resolved": "https://registry.npmjs.org/rehype-expressive-code/-/rehype-expressive-code-0.41.6.tgz",
+ "integrity": "sha512-aBMX8kxPtjmDSFUdZlAWJkMvsQ4ZMASfee90JWIAV8tweltXLzkWC3q++43ToTelI8ac5iC0B3/S/Cl4Ql1y2g==",
+ "license": "MIT",
+ "dependencies": {
+ "expressive-code": "^0.41.6"
+ }
+ },
+ "node_modules/rehype-format": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/rehype-format/-/rehype-format-5.0.1.tgz",
+ "integrity": "sha512-zvmVru9uB0josBVpr946OR8ui7nJEdzZobwLOOqHb/OOD88W0Vk2SqLwoVOj0fM6IPCCO6TaV9CvQvJMWwukFQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hast-util-format": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/rehype-parse": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz",
+ "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hast-util-from-html": "^2.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/rehype-raw": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz",
+ "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hast-util-raw": "^9.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/rehype-recma": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz",
+ "integrity": "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "hast-util-to-estree": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/rehype-stringify": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz",
+ "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hast-util-to-html": "^9.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-directive": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-3.0.1.tgz",
+ "integrity": "sha512-gwglrEQEZcZYgVyG1tQuA+h58EZfq5CSULw7J90AFuCTyib1thgHPoqQ+h9iFvU6R+vnZ5oNFQR5QKgGpk741A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "mdast-util-directive": "^3.0.0",
+ "micromark-extension-directive": "^3.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-gfm": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz",
+ "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "mdast-util-gfm": "^3.0.0",
+ "micromark-extension-gfm": "^3.0.0",
+ "remark-parse": "^11.0.0",
+ "remark-stringify": "^11.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-mdx": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.1.tgz",
+ "integrity": "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==",
+ "license": "MIT",
+ "dependencies": {
+ "mdast-util-mdx": "^3.0.0",
+ "micromark-extension-mdxjs": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-parse": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz",
+ "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-rehype": {
+ "version": "11.1.2",
+ "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz",
+ "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "mdast-util-to-hast": "^13.0.0",
+ "unified": "^11.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-smartypants": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-3.0.2.tgz",
+ "integrity": "sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==",
+ "license": "MIT",
+ "dependencies": {
+ "retext": "^9.0.0",
+ "retext-smartypants": "^6.0.0",
+ "unified": "^11.0.4",
+ "unist-util-visit": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/remark-stringify": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz",
+ "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "mdast-util-to-markdown": "^2.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/retext": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz",
+ "integrity": "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/nlcst": "^2.0.0",
+ "retext-latin": "^4.0.0",
+ "retext-stringify": "^4.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/retext-latin": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-4.0.0.tgz",
+ "integrity": "sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/nlcst": "^2.0.0",
+ "parse-latin": "^7.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/retext-smartypants": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.2.0.tgz",
+ "integrity": "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/nlcst": "^2.0.0",
+ "nlcst-to-string": "^4.0.0",
+ "unist-util-visit": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/retext-stringify": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-4.0.0.tgz",
+ "integrity": "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/nlcst": "^2.0.0",
+ "nlcst-to-string": "^4.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz",
+ "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "1.0.8"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.57.1",
+ "@rollup/rollup-android-arm64": "4.57.1",
+ "@rollup/rollup-darwin-arm64": "4.57.1",
+ "@rollup/rollup-darwin-x64": "4.57.1",
+ "@rollup/rollup-freebsd-arm64": "4.57.1",
+ "@rollup/rollup-freebsd-x64": "4.57.1",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.57.1",
+ "@rollup/rollup-linux-arm-musleabihf": "4.57.1",
+ "@rollup/rollup-linux-arm64-gnu": "4.57.1",
+ "@rollup/rollup-linux-arm64-musl": "4.57.1",
+ "@rollup/rollup-linux-loong64-gnu": "4.57.1",
+ "@rollup/rollup-linux-loong64-musl": "4.57.1",
+ "@rollup/rollup-linux-ppc64-gnu": "4.57.1",
+ "@rollup/rollup-linux-ppc64-musl": "4.57.1",
+ "@rollup/rollup-linux-riscv64-gnu": "4.57.1",
+ "@rollup/rollup-linux-riscv64-musl": "4.57.1",
+ "@rollup/rollup-linux-s390x-gnu": "4.57.1",
+ "@rollup/rollup-linux-x64-gnu": "4.57.1",
+ "@rollup/rollup-linux-x64-musl": "4.57.1",
+ "@rollup/rollup-openbsd-x64": "4.57.1",
+ "@rollup/rollup-openharmony-arm64": "4.57.1",
+ "@rollup/rollup-win32-arm64-msvc": "4.57.1",
+ "@rollup/rollup-win32-ia32-msvc": "4.57.1",
+ "@rollup/rollup-win32-x64-gnu": "4.57.1",
+ "@rollup/rollup-win32-x64-msvc": "4.57.1",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/sax": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz",
+ "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=11.0.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.7.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
+ "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/sharp": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
+ "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@img/colour": "^1.0.0",
+ "detect-libc": "^2.1.2",
+ "semver": "^7.7.3"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-darwin-arm64": "0.34.5",
+ "@img/sharp-darwin-x64": "0.34.5",
+ "@img/sharp-libvips-darwin-arm64": "1.2.4",
+ "@img/sharp-libvips-darwin-x64": "1.2.4",
+ "@img/sharp-libvips-linux-arm": "1.2.4",
+ "@img/sharp-libvips-linux-arm64": "1.2.4",
+ "@img/sharp-libvips-linux-ppc64": "1.2.4",
+ "@img/sharp-libvips-linux-riscv64": "1.2.4",
+ "@img/sharp-libvips-linux-s390x": "1.2.4",
+ "@img/sharp-libvips-linux-x64": "1.2.4",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.4",
+ "@img/sharp-linux-arm": "0.34.5",
+ "@img/sharp-linux-arm64": "0.34.5",
+ "@img/sharp-linux-ppc64": "0.34.5",
+ "@img/sharp-linux-riscv64": "0.34.5",
+ "@img/sharp-linux-s390x": "0.34.5",
+ "@img/sharp-linux-x64": "0.34.5",
+ "@img/sharp-linuxmusl-arm64": "0.34.5",
+ "@img/sharp-linuxmusl-x64": "0.34.5",
+ "@img/sharp-wasm32": "0.34.5",
+ "@img/sharp-win32-arm64": "0.34.5",
+ "@img/sharp-win32-ia32": "0.34.5",
+ "@img/sharp-win32-x64": "0.34.5"
+ }
+ },
+ "node_modules/shiki": {
+ "version": "3.22.0",
+ "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.22.0.tgz",
+ "integrity": "sha512-LBnhsoYEe0Eou4e1VgJACes+O6S6QC0w71fCSp5Oya79inkwkm15gQ1UF6VtQ8j/taMDh79hAB49WUk8ALQW3g==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/core": "3.22.0",
+ "@shikijs/engine-javascript": "3.22.0",
+ "@shikijs/engine-oniguruma": "3.22.0",
+ "@shikijs/langs": "3.22.0",
+ "@shikijs/themes": "3.22.0",
+ "@shikijs/types": "3.22.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4"
+ }
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "license": "MIT"
+ },
+ "node_modules/sitemap": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-8.0.2.tgz",
+ "integrity": "sha512-LwktpJcyZDoa0IL6KT++lQ53pbSrx2c9ge41/SeLTyqy2XUNA6uR4+P9u5IVo5lPeL2arAcOKn1aZAxoYbCKlQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "^17.0.5",
+ "@types/sax": "^1.2.1",
+ "arg": "^5.0.0",
+ "sax": "^1.4.1"
+ },
+ "bin": {
+ "sitemap": "dist/cli.js"
+ },
+ "engines": {
+ "node": ">=14.0.0",
+ "npm": ">=6.0.0"
+ }
+ },
+ "node_modules/sitemap/node_modules/@types/node": {
+ "version": "17.0.45",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz",
+ "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==",
+ "license": "MIT"
+ },
+ "node_modules/smol-toml": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.0.tgz",
+ "integrity": "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/cyyynthia"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.7.6",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz",
+ "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/space-separated-tokens": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz",
+ "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/stream-replace-string": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/stream-replace-string/-/stream-replace-string-2.0.0.tgz",
+ "integrity": "sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==",
+ "license": "MIT"
+ },
+ "node_modules/string-width": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
+ "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^10.3.0",
+ "get-east-asian-width": "^1.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/stringify-entities": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
+ "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==",
+ "license": "MIT",
+ "dependencies": {
+ "character-entities-html4": "^2.0.0",
+ "character-entities-legacy": "^3.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz",
+ "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/style-to-js": {
+ "version": "1.1.21",
+ "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz",
+ "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==",
+ "license": "MIT",
+ "dependencies": {
+ "style-to-object": "1.0.14"
+ }
+ },
+ "node_modules/style-to-object": {
+ "version": "1.0.14",
+ "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz",
+ "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==",
+ "license": "MIT",
+ "dependencies": {
+ "inline-style-parser": "0.2.7"
+ }
+ },
+ "node_modules/svgo": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.0.tgz",
+ "integrity": "sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==",
+ "license": "MIT",
+ "dependencies": {
+ "commander": "^11.1.0",
+ "css-select": "^5.1.0",
+ "css-tree": "^3.0.1",
+ "css-what": "^6.1.0",
+ "csso": "^5.0.5",
+ "picocolors": "^1.1.1",
+ "sax": "^1.4.1"
+ },
+ "bin": {
+ "svgo": "bin/svgo.js"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/svgo"
+ }
+ },
+ "node_modules/tiny-inflate": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
+ "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==",
+ "license": "MIT"
+ },
+ "node_modules/tinyexec": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz",
+ "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.15",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
+ "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/trim-lines": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
+ "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/trough": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz",
+ "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/tsconfck": {
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.6.tgz",
+ "integrity": "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==",
+ "license": "MIT",
+ "bin": {
+ "tsconfck": "bin/tsconfck.js"
+ },
+ "engines": {
+ "node": "^18 || >=20"
+ },
+ "peerDependencies": {
+ "typescript": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD",
+ "optional": true
+ },
+ "node_modules/type-fest": {
+ "version": "4.41.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
+ "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/ufo": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz",
+ "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==",
+ "license": "MIT"
+ },
+ "node_modules/ultrahtml": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.6.0.tgz",
+ "integrity": "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==",
+ "license": "MIT"
+ },
+ "node_modules/uncrypto": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz",
+ "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==",
+ "license": "MIT"
+ },
+ "node_modules/undici-types": {
+ "version": "7.16.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
+ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
+ "license": "MIT"
+ },
+ "node_modules/unified": {
+ "version": "11.0.5",
+ "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz",
+ "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "bail": "^2.0.0",
+ "devlop": "^1.0.0",
+ "extend": "^3.0.0",
+ "is-plain-obj": "^4.0.0",
+ "trough": "^2.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unifont": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.7.3.tgz",
+ "integrity": "sha512-b0GtQzKCyuSHGsfj5vyN8st7muZ6VCI4XD4vFlr7Uy1rlWVYxC3npnfk8MyreHxJYrz1ooLDqDzFe9XqQTlAhA==",
+ "license": "MIT",
+ "dependencies": {
+ "css-tree": "^3.1.0",
+ "ofetch": "^1.5.1",
+ "ohash": "^2.0.11"
+ }
+ },
+ "node_modules/unist-util-find-after": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz",
+ "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-is": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz",
+ "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-modify-children": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-4.0.0.tgz",
+ "integrity": "sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "array-iterate": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-position": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz",
+ "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-position-from-estree": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz",
+ "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-remove-position": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz",
+ "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-visit": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-stringify-position": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
+ "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz",
+ "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0",
+ "unist-util-visit-parents": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit-children": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-3.0.0.tgz",
+ "integrity": "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit-parents": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz",
+ "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unstorage": {
+ "version": "1.17.4",
+ "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.4.tgz",
+ "integrity": "sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw==",
+ "license": "MIT",
+ "dependencies": {
+ "anymatch": "^3.1.3",
+ "chokidar": "^5.0.0",
+ "destr": "^2.0.5",
+ "h3": "^1.15.5",
+ "lru-cache": "^11.2.0",
+ "node-fetch-native": "^1.6.7",
+ "ofetch": "^1.5.1",
+ "ufo": "^1.6.3"
+ },
+ "peerDependencies": {
+ "@azure/app-configuration": "^1.8.0",
+ "@azure/cosmos": "^4.2.0",
+ "@azure/data-tables": "^13.3.0",
+ "@azure/identity": "^4.6.0",
+ "@azure/keyvault-secrets": "^4.9.0",
+ "@azure/storage-blob": "^12.26.0",
+ "@capacitor/preferences": "^6 || ^7 || ^8",
+ "@deno/kv": ">=0.9.0",
+ "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0",
+ "@planetscale/database": "^1.19.0",
+ "@upstash/redis": "^1.34.3",
+ "@vercel/blob": ">=0.27.1",
+ "@vercel/functions": "^2.2.12 || ^3.0.0",
+ "@vercel/kv": "^1 || ^2 || ^3",
+ "aws4fetch": "^1.0.20",
+ "db0": ">=0.2.1",
+ "idb-keyval": "^6.2.1",
+ "ioredis": "^5.4.2",
+ "uploadthing": "^7.4.4"
+ },
+ "peerDependenciesMeta": {
+ "@azure/app-configuration": {
+ "optional": true
+ },
+ "@azure/cosmos": {
+ "optional": true
+ },
+ "@azure/data-tables": {
+ "optional": true
+ },
+ "@azure/identity": {
+ "optional": true
+ },
+ "@azure/keyvault-secrets": {
+ "optional": true
+ },
+ "@azure/storage-blob": {
+ "optional": true
+ },
+ "@capacitor/preferences": {
+ "optional": true
+ },
+ "@deno/kv": {
+ "optional": true
+ },
+ "@netlify/blobs": {
+ "optional": true
+ },
+ "@planetscale/database": {
+ "optional": true
+ },
+ "@upstash/redis": {
+ "optional": true
+ },
+ "@vercel/blob": {
+ "optional": true
+ },
+ "@vercel/functions": {
+ "optional": true
+ },
+ "@vercel/kv": {
+ "optional": true
+ },
+ "aws4fetch": {
+ "optional": true
+ },
+ "db0": {
+ "optional": true
+ },
+ "idb-keyval": {
+ "optional": true
+ },
+ "ioredis": {
+ "optional": true
+ },
+ "uploadthing": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "license": "MIT"
+ },
+ "node_modules/vfile": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
+ "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-location": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz",
+ "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-message": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz",
+ "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-stringify-position": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vite": {
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz",
+ "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.25.0",
+ "fdir": "^6.4.4",
+ "picomatch": "^4.0.2",
+ "postcss": "^8.5.3",
+ "rollup": "^4.34.9",
+ "tinyglobby": "^0.2.13"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
+ "jiti": ">=1.21.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "sass-embedded": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vitefu": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.1.tgz",
+ "integrity": "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==",
+ "license": "MIT",
+ "workspaces": [
+ "tests/deps/*",
+ "tests/projects/*",
+ "tests/projects/workspace/packages/*"
+ ],
+ "peerDependencies": {
+ "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0"
+ },
+ "peerDependenciesMeta": {
+ "vite": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/web-namespaces": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz",
+ "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/which-pm-runs": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz",
+ "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/widest-line": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz",
+ "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==",
+ "license": "MIT",
+ "dependencies": {
+ "string-width": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz",
+ "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.2.1",
+ "string-width": "^7.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/xxhash-wasm": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz",
+ "integrity": "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==",
+ "license": "MIT"
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz",
+ "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/yocto-spinner": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/yocto-spinner/-/yocto-spinner-0.2.3.tgz",
+ "integrity": "sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ==",
+ "license": "MIT",
+ "dependencies": {
+ "yoctocolors": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=18.19"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/yoctocolors": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz",
+ "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/zod": {
+ "version": "3.25.76",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
+ "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/zod-to-json-schema": {
+ "version": "3.25.1",
+ "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz",
+ "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==",
+ "license": "ISC",
+ "peerDependencies": {
+ "zod": "^3.25 || ^4"
+ }
+ },
+ "node_modules/zod-to-ts": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/zod-to-ts/-/zod-to-ts-1.2.0.tgz",
+ "integrity": "sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==",
+ "peerDependencies": {
+ "typescript": "^4.9.4 || ^5.0.2",
+ "zod": "^3"
+ }
+ },
+ "node_modules/zwitch": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
+ "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ }
+ }
+}
diff --git a/doccs/site/package.json b/doccs/site/package.json
new file mode 100644
index 0000000..10b3ca1
--- /dev/null
+++ b/doccs/site/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "doccs-site",
+ "type": "module",
+ "version": "0.0.1",
+ "scripts": {
+ "dev": "astro dev",
+ "start": "astro dev",
+ "build": "astro build",
+ "preview": "astro preview",
+ "astro": "astro"
+ },
+ "dependencies": {
+ "@astrojs/starlight": "^0.37.6",
+ "astro": "^5.6.1",
+ "sharp": "^0.34.2"
+ }
+}
\ No newline at end of file
diff --git a/doccs/site/public/favicon.svg b/doccs/site/public/favicon.svg
new file mode 100644
index 0000000..cba5ac1
--- /dev/null
+++ b/doccs/site/public/favicon.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/doccs/site/public/screenshots/admin-automation-api.png b/doccs/site/public/screenshots/admin-automation-api.png
new file mode 100644
index 0000000..029e4a4
Binary files /dev/null and b/doccs/site/public/screenshots/admin-automation-api.png differ
diff --git a/doccs/site/public/screenshots/admin-backup-download.png b/doccs/site/public/screenshots/admin-backup-download.png
new file mode 100644
index 0000000..d3c2d62
Binary files /dev/null and b/doccs/site/public/screenshots/admin-backup-download.png differ
diff --git a/doccs/site/public/screenshots/admin-backups--tab-backups.png b/doccs/site/public/screenshots/admin-backups--tab-backups.png
new file mode 100644
index 0000000..4d889a1
Binary files /dev/null and b/doccs/site/public/screenshots/admin-backups--tab-backups.png differ
diff --git a/doccs/site/public/screenshots/admin-backups--tab-destinations.png b/doccs/site/public/screenshots/admin-backups--tab-destinations.png
new file mode 100644
index 0000000..3250684
Binary files /dev/null and b/doccs/site/public/screenshots/admin-backups--tab-destinations.png differ
diff --git a/doccs/site/public/screenshots/admin-backups--tab-schedules.png b/doccs/site/public/screenshots/admin-backups--tab-schedules.png
new file mode 100644
index 0000000..91e70ab
Binary files /dev/null and b/doccs/site/public/screenshots/admin-backups--tab-schedules.png differ
diff --git a/doccs/site/public/screenshots/admin-backups.png b/doccs/site/public/screenshots/admin-backups.png
new file mode 100644
index 0000000..3250684
Binary files /dev/null and b/doccs/site/public/screenshots/admin-backups.png differ
diff --git a/doccs/site/public/screenshots/admin-cpanel-migration.png b/doccs/site/public/screenshots/admin-cpanel-migration.png
new file mode 100644
index 0000000..431679f
Binary files /dev/null and b/doccs/site/public/screenshots/admin-cpanel-migration.png differ
diff --git a/doccs/site/public/screenshots/admin-dashboard.png b/doccs/site/public/screenshots/admin-dashboard.png
new file mode 100644
index 0000000..2c913fc
Binary files /dev/null and b/doccs/site/public/screenshots/admin-dashboard.png differ
diff --git a/doccs/site/public/screenshots/admin-database-tuning.png b/doccs/site/public/screenshots/admin-database-tuning.png
new file mode 100644
index 0000000..63c95fc
Binary files /dev/null and b/doccs/site/public/screenshots/admin-database-tuning.png differ
diff --git a/doccs/site/public/screenshots/admin-dns-zones.png b/doccs/site/public/screenshots/admin-dns-zones.png
new file mode 100644
index 0000000..955e643
Binary files /dev/null and b/doccs/site/public/screenshots/admin-dns-zones.png differ
diff --git a/doccs/site/public/screenshots/admin-email-logs.png b/doccs/site/public/screenshots/admin-email-logs.png
new file mode 100644
index 0000000..38b095c
Binary files /dev/null and b/doccs/site/public/screenshots/admin-email-logs.png differ
diff --git a/doccs/site/public/screenshots/admin-email-queue.png b/doccs/site/public/screenshots/admin-email-queue.png
new file mode 100644
index 0000000..38b095c
Binary files /dev/null and b/doccs/site/public/screenshots/admin-email-queue.png differ
diff --git a/doccs/site/public/screenshots/admin-geo-block-rules-5-edit.png b/doccs/site/public/screenshots/admin-geo-block-rules-5-edit.png
new file mode 100644
index 0000000..c2a17c2
Binary files /dev/null and b/doccs/site/public/screenshots/admin-geo-block-rules-5-edit.png differ
diff --git a/doccs/site/public/screenshots/admin-geo-block-rules-create.png b/doccs/site/public/screenshots/admin-geo-block-rules-create.png
new file mode 100644
index 0000000..dc7f9ed
Binary files /dev/null and b/doccs/site/public/screenshots/admin-geo-block-rules-create.png differ
diff --git a/doccs/site/public/screenshots/admin-geo-block-rules-edit.png b/doccs/site/public/screenshots/admin-geo-block-rules-edit.png
new file mode 100644
index 0000000..c2a17c2
Binary files /dev/null and b/doccs/site/public/screenshots/admin-geo-block-rules-edit.png differ
diff --git a/doccs/site/public/screenshots/admin-geo-block-rules.png b/doccs/site/public/screenshots/admin-geo-block-rules.png
new file mode 100644
index 0000000..8d532af
Binary files /dev/null and b/doccs/site/public/screenshots/admin-geo-block-rules.png differ
diff --git a/doccs/site/public/screenshots/admin-home.png b/doccs/site/public/screenshots/admin-home.png
new file mode 100644
index 0000000..2c913fc
Binary files /dev/null and b/doccs/site/public/screenshots/admin-home.png differ
diff --git a/doccs/site/public/screenshots/admin-hosting-packages-1-edit.png b/doccs/site/public/screenshots/admin-hosting-packages-1-edit.png
new file mode 100644
index 0000000..0476fa2
Binary files /dev/null and b/doccs/site/public/screenshots/admin-hosting-packages-1-edit.png differ
diff --git a/doccs/site/public/screenshots/admin-hosting-packages-create.png b/doccs/site/public/screenshots/admin-hosting-packages-create.png
new file mode 100644
index 0000000..03ac40a
Binary files /dev/null and b/doccs/site/public/screenshots/admin-hosting-packages-create.png differ
diff --git a/doccs/site/public/screenshots/admin-hosting-packages-edit.png b/doccs/site/public/screenshots/admin-hosting-packages-edit.png
new file mode 100644
index 0000000..0476fa2
Binary files /dev/null and b/doccs/site/public/screenshots/admin-hosting-packages-edit.png differ
diff --git a/doccs/site/public/screenshots/admin-hosting-packages.png b/doccs/site/public/screenshots/admin-hosting-packages.png
new file mode 100644
index 0000000..87a6a67
Binary files /dev/null and b/doccs/site/public/screenshots/admin-hosting-packages.png differ
diff --git a/doccs/site/public/screenshots/admin-ip-addresses.png b/doccs/site/public/screenshots/admin-ip-addresses.png
new file mode 100644
index 0000000..b38642c
Binary files /dev/null and b/doccs/site/public/screenshots/admin-ip-addresses.png differ
diff --git a/doccs/site/public/screenshots/admin-login.png b/doccs/site/public/screenshots/admin-login.png
new file mode 100644
index 0000000..cc31f1f
Binary files /dev/null and b/doccs/site/public/screenshots/admin-login.png differ
diff --git a/doccs/site/public/screenshots/admin-migration--tab-cpanel-migration.png b/doccs/site/public/screenshots/admin-migration--tab-cpanel-migration.png
new file mode 100644
index 0000000..1693a74
Binary files /dev/null and b/doccs/site/public/screenshots/admin-migration--tab-cpanel-migration.png differ
diff --git a/doccs/site/public/screenshots/admin-migration--tab-whm-migration.png b/doccs/site/public/screenshots/admin-migration--tab-whm-migration.png
new file mode 100644
index 0000000..536b96e
Binary files /dev/null and b/doccs/site/public/screenshots/admin-migration--tab-whm-migration.png differ
diff --git a/doccs/site/public/screenshots/admin-migration.png b/doccs/site/public/screenshots/admin-migration.png
new file mode 100644
index 0000000..1693a74
Binary files /dev/null and b/doccs/site/public/screenshots/admin-migration.png differ
diff --git a/doccs/site/public/screenshots/admin-password-reset-request.png b/doccs/site/public/screenshots/admin-password-reset-request.png
new file mode 100644
index 0000000..ec6075d
Binary files /dev/null and b/doccs/site/public/screenshots/admin-password-reset-request.png differ
diff --git a/doccs/site/public/screenshots/admin-password-reset-reset.png b/doccs/site/public/screenshots/admin-password-reset-reset.png
new file mode 100644
index 0000000..4f44da7
Binary files /dev/null and b/doccs/site/public/screenshots/admin-password-reset-reset.png differ
diff --git a/doccs/site/public/screenshots/admin-php-manager.png b/doccs/site/public/screenshots/admin-php-manager.png
new file mode 100644
index 0000000..234a681
Binary files /dev/null and b/doccs/site/public/screenshots/admin-php-manager.png differ
diff --git a/doccs/site/public/screenshots/admin-security--tab-antivirus.png b/doccs/site/public/screenshots/admin-security--tab-antivirus.png
new file mode 100644
index 0000000..012372a
Binary files /dev/null and b/doccs/site/public/screenshots/admin-security--tab-antivirus.png differ
diff --git a/doccs/site/public/screenshots/admin-security--tab-fail2ban.png b/doccs/site/public/screenshots/admin-security--tab-fail2ban.png
new file mode 100644
index 0000000..012372a
Binary files /dev/null and b/doccs/site/public/screenshots/admin-security--tab-fail2ban.png differ
diff --git a/doccs/site/public/screenshots/admin-security--tab-firewall.png b/doccs/site/public/screenshots/admin-security--tab-firewall.png
new file mode 100644
index 0000000..35c33fc
Binary files /dev/null and b/doccs/site/public/screenshots/admin-security--tab-firewall.png differ
diff --git a/doccs/site/public/screenshots/admin-security--tab-modsecurity-waf.png b/doccs/site/public/screenshots/admin-security--tab-modsecurity-waf.png
new file mode 100644
index 0000000..b414d82
Binary files /dev/null and b/doccs/site/public/screenshots/admin-security--tab-modsecurity-waf.png differ
diff --git a/doccs/site/public/screenshots/admin-security--tab-overview.png b/doccs/site/public/screenshots/admin-security--tab-overview.png
new file mode 100644
index 0000000..1611179
Binary files /dev/null and b/doccs/site/public/screenshots/admin-security--tab-overview.png differ
diff --git a/doccs/site/public/screenshots/admin-security--tab-ssh.png b/doccs/site/public/screenshots/admin-security--tab-ssh.png
new file mode 100644
index 0000000..012372a
Binary files /dev/null and b/doccs/site/public/screenshots/admin-security--tab-ssh.png differ
diff --git a/doccs/site/public/screenshots/admin-security--tab-vulnerability-scanner.png b/doccs/site/public/screenshots/admin-security--tab-vulnerability-scanner.png
new file mode 100644
index 0000000..e7aa16d
Binary files /dev/null and b/doccs/site/public/screenshots/admin-security--tab-vulnerability-scanner.png differ
diff --git a/doccs/site/public/screenshots/admin-security.png b/doccs/site/public/screenshots/admin-security.png
new file mode 100644
index 0000000..1611179
Binary files /dev/null and b/doccs/site/public/screenshots/admin-security.png differ
diff --git a/doccs/site/public/screenshots/admin-server-settings--tab-database-tuning.png b/doccs/site/public/screenshots/admin-server-settings--tab-database-tuning.png
new file mode 100644
index 0000000..1b25340
Binary files /dev/null and b/doccs/site/public/screenshots/admin-server-settings--tab-database-tuning.png differ
diff --git a/doccs/site/public/screenshots/admin-server-settings--tab-dns.png b/doccs/site/public/screenshots/admin-server-settings--tab-dns.png
new file mode 100644
index 0000000..90cd53f
Binary files /dev/null and b/doccs/site/public/screenshots/admin-server-settings--tab-dns.png differ
diff --git a/doccs/site/public/screenshots/admin-server-settings--tab-email.png b/doccs/site/public/screenshots/admin-server-settings--tab-email.png
new file mode 100644
index 0000000..31de073
Binary files /dev/null and b/doccs/site/public/screenshots/admin-server-settings--tab-email.png differ
diff --git a/doccs/site/public/screenshots/admin-server-settings--tab-general.png b/doccs/site/public/screenshots/admin-server-settings--tab-general.png
new file mode 100644
index 0000000..a745c29
Binary files /dev/null and b/doccs/site/public/screenshots/admin-server-settings--tab-general.png differ
diff --git a/doccs/site/public/screenshots/admin-server-settings--tab-notifications.png b/doccs/site/public/screenshots/admin-server-settings--tab-notifications.png
new file mode 100644
index 0000000..1c925de
Binary files /dev/null and b/doccs/site/public/screenshots/admin-server-settings--tab-notifications.png differ
diff --git a/doccs/site/public/screenshots/admin-server-settings--tab-php-fpm.png b/doccs/site/public/screenshots/admin-server-settings--tab-php-fpm.png
new file mode 100644
index 0000000..65ea45f
Binary files /dev/null and b/doccs/site/public/screenshots/admin-server-settings--tab-php-fpm.png differ
diff --git a/doccs/site/public/screenshots/admin-server-settings--tab-storage.png b/doccs/site/public/screenshots/admin-server-settings--tab-storage.png
new file mode 100644
index 0000000..9ed0ba4
Binary files /dev/null and b/doccs/site/public/screenshots/admin-server-settings--tab-storage.png differ
diff --git a/doccs/site/public/screenshots/admin-server-settings.png b/doccs/site/public/screenshots/admin-server-settings.png
new file mode 100644
index 0000000..a745c29
Binary files /dev/null and b/doccs/site/public/screenshots/admin-server-settings.png differ
diff --git a/doccs/site/public/screenshots/admin-server-status.png b/doccs/site/public/screenshots/admin-server-status.png
new file mode 100644
index 0000000..2204a5d
Binary files /dev/null and b/doccs/site/public/screenshots/admin-server-status.png differ
diff --git a/doccs/site/public/screenshots/admin-server-updates.png b/doccs/site/public/screenshots/admin-server-updates.png
new file mode 100644
index 0000000..5a2172d
Binary files /dev/null and b/doccs/site/public/screenshots/admin-server-updates.png differ
diff --git a/doccs/site/public/screenshots/admin-services.png b/doccs/site/public/screenshots/admin-services.png
new file mode 100644
index 0000000..1ccec0f
Binary files /dev/null and b/doccs/site/public/screenshots/admin-services.png differ
diff --git a/doccs/site/public/screenshots/admin-ssl-manager.png b/doccs/site/public/screenshots/admin-ssl-manager.png
new file mode 100644
index 0000000..e75e384
Binary files /dev/null and b/doccs/site/public/screenshots/admin-ssl-manager.png differ
diff --git a/doccs/site/public/screenshots/admin-two-factor-challenge.png b/doccs/site/public/screenshots/admin-two-factor-challenge.png
new file mode 100644
index 0000000..4231887
Binary files /dev/null and b/doccs/site/public/screenshots/admin-two-factor-challenge.png differ
diff --git a/doccs/site/public/screenshots/admin-users-1-edit.png b/doccs/site/public/screenshots/admin-users-1-edit.png
new file mode 100644
index 0000000..f8ed56e
Binary files /dev/null and b/doccs/site/public/screenshots/admin-users-1-edit.png differ
diff --git a/doccs/site/public/screenshots/admin-users-create.png b/doccs/site/public/screenshots/admin-users-create.png
new file mode 100644
index 0000000..3e5e9d5
Binary files /dev/null and b/doccs/site/public/screenshots/admin-users-create.png differ
diff --git a/doccs/site/public/screenshots/admin-users-edit.png b/doccs/site/public/screenshots/admin-users-edit.png
new file mode 100644
index 0000000..f8ed56e
Binary files /dev/null and b/doccs/site/public/screenshots/admin-users-edit.png differ
diff --git a/doccs/site/public/screenshots/admin-users.png b/doccs/site/public/screenshots/admin-users.png
new file mode 100644
index 0000000..c011d59
Binary files /dev/null and b/doccs/site/public/screenshots/admin-users.png differ
diff --git a/doccs/site/public/screenshots/admin-waf.png b/doccs/site/public/screenshots/admin-waf.png
new file mode 100644
index 0000000..ebc5268
Binary files /dev/null and b/doccs/site/public/screenshots/admin-waf.png differ
diff --git a/doccs/site/public/screenshots/admin-webhook-endpoints-1-edit.png b/doccs/site/public/screenshots/admin-webhook-endpoints-1-edit.png
new file mode 100644
index 0000000..7764fa3
Binary files /dev/null and b/doccs/site/public/screenshots/admin-webhook-endpoints-1-edit.png differ
diff --git a/doccs/site/public/screenshots/admin-webhook-endpoints-create.png b/doccs/site/public/screenshots/admin-webhook-endpoints-create.png
new file mode 100644
index 0000000..b5fe648
Binary files /dev/null and b/doccs/site/public/screenshots/admin-webhook-endpoints-create.png differ
diff --git a/doccs/site/public/screenshots/admin-webhook-endpoints-edit.png b/doccs/site/public/screenshots/admin-webhook-endpoints-edit.png
new file mode 100644
index 0000000..7764fa3
Binary files /dev/null and b/doccs/site/public/screenshots/admin-webhook-endpoints-edit.png differ
diff --git a/doccs/site/public/screenshots/admin-webhook-endpoints.png b/doccs/site/public/screenshots/admin-webhook-endpoints.png
new file mode 100644
index 0000000..4537eb4
Binary files /dev/null and b/doccs/site/public/screenshots/admin-webhook-endpoints.png differ
diff --git a/doccs/site/public/screenshots/admin-whm-migration.png b/doccs/site/public/screenshots/admin-whm-migration.png
new file mode 100644
index 0000000..e47a01c
Binary files /dev/null and b/doccs/site/public/screenshots/admin-whm-migration.png differ
diff --git a/doccs/site/public/screenshots/user-backup-download.png b/doccs/site/public/screenshots/user-backup-download.png
new file mode 100644
index 0000000..e37d205
Binary files /dev/null and b/doccs/site/public/screenshots/user-backup-download.png differ
diff --git a/doccs/site/public/screenshots/user-backups--tab-my-backups.png b/doccs/site/public/screenshots/user-backups--tab-my-backups.png
new file mode 100644
index 0000000..622d004
Binary files /dev/null and b/doccs/site/public/screenshots/user-backups--tab-my-backups.png differ
diff --git a/doccs/site/public/screenshots/user-backups--tab-restore-history.png b/doccs/site/public/screenshots/user-backups--tab-restore-history.png
new file mode 100644
index 0000000..e61935b
Binary files /dev/null and b/doccs/site/public/screenshots/user-backups--tab-restore-history.png differ
diff --git a/doccs/site/public/screenshots/user-backups--tab-server-backups.png b/doccs/site/public/screenshots/user-backups--tab-server-backups.png
new file mode 100644
index 0000000..26d6b5b
Binary files /dev/null and b/doccs/site/public/screenshots/user-backups--tab-server-backups.png differ
diff --git a/doccs/site/public/screenshots/user-backups--tab-sftp-destinations.png b/doccs/site/public/screenshots/user-backups--tab-sftp-destinations.png
new file mode 100644
index 0000000..6dda5e7
Binary files /dev/null and b/doccs/site/public/screenshots/user-backups--tab-sftp-destinations.png differ
diff --git a/doccs/site/public/screenshots/user-backups.png b/doccs/site/public/screenshots/user-backups.png
new file mode 100644
index 0000000..622d004
Binary files /dev/null and b/doccs/site/public/screenshots/user-backups.png differ
diff --git a/doccs/site/public/screenshots/user-cdn-integration.png b/doccs/site/public/screenshots/user-cdn-integration.png
new file mode 100644
index 0000000..19ca539
Binary files /dev/null and b/doccs/site/public/screenshots/user-cdn-integration.png differ
diff --git a/doccs/site/public/screenshots/user-cpanel-migration.png b/doccs/site/public/screenshots/user-cpanel-migration.png
new file mode 100644
index 0000000..76c81a2
Binary files /dev/null and b/doccs/site/public/screenshots/user-cpanel-migration.png differ
diff --git a/doccs/site/public/screenshots/user-cron-jobs.png b/doccs/site/public/screenshots/user-cron-jobs.png
new file mode 100644
index 0000000..6711257
Binary files /dev/null and b/doccs/site/public/screenshots/user-cron-jobs.png differ
diff --git a/doccs/site/public/screenshots/user-dashboard.png b/doccs/site/public/screenshots/user-dashboard.png
new file mode 100644
index 0000000..f9b2a38
Binary files /dev/null and b/doccs/site/public/screenshots/user-dashboard.png differ
diff --git a/doccs/site/public/screenshots/user-databases.png b/doccs/site/public/screenshots/user-databases.png
new file mode 100644
index 0000000..a9b5f24
Binary files /dev/null and b/doccs/site/public/screenshots/user-databases.png differ
diff --git a/doccs/site/public/screenshots/user-dns-records.png b/doccs/site/public/screenshots/user-dns-records.png
new file mode 100644
index 0000000..467a63c
Binary files /dev/null and b/doccs/site/public/screenshots/user-dns-records.png differ
diff --git a/doccs/site/public/screenshots/user-domains.png b/doccs/site/public/screenshots/user-domains.png
new file mode 100644
index 0000000..f8193a4
Binary files /dev/null and b/doccs/site/public/screenshots/user-domains.png differ
diff --git a/doccs/site/public/screenshots/user-email--tab-autoresponders.png b/doccs/site/public/screenshots/user-email--tab-autoresponders.png
new file mode 100644
index 0000000..87b8565
Binary files /dev/null and b/doccs/site/public/screenshots/user-email--tab-autoresponders.png differ
diff --git a/doccs/site/public/screenshots/user-email--tab-catch-all.png b/doccs/site/public/screenshots/user-email--tab-catch-all.png
new file mode 100644
index 0000000..206c277
Binary files /dev/null and b/doccs/site/public/screenshots/user-email--tab-catch-all.png differ
diff --git a/doccs/site/public/screenshots/user-email--tab-forwarders.png b/doccs/site/public/screenshots/user-email--tab-forwarders.png
new file mode 100644
index 0000000..4041c7a
Binary files /dev/null and b/doccs/site/public/screenshots/user-email--tab-forwarders.png differ
diff --git a/doccs/site/public/screenshots/user-email--tab-logs.png b/doccs/site/public/screenshots/user-email--tab-logs.png
new file mode 100644
index 0000000..2af2b03
Binary files /dev/null and b/doccs/site/public/screenshots/user-email--tab-logs.png differ
diff --git a/doccs/site/public/screenshots/user-email--tab-mailboxes.png b/doccs/site/public/screenshots/user-email--tab-mailboxes.png
new file mode 100644
index 0000000..dec06fa
Binary files /dev/null and b/doccs/site/public/screenshots/user-email--tab-mailboxes.png differ
diff --git a/doccs/site/public/screenshots/user-email--tab-spam-settings.png b/doccs/site/public/screenshots/user-email--tab-spam-settings.png
new file mode 100644
index 0000000..388ac6f
Binary files /dev/null and b/doccs/site/public/screenshots/user-email--tab-spam-settings.png differ
diff --git a/doccs/site/public/screenshots/user-email.png b/doccs/site/public/screenshots/user-email.png
new file mode 100644
index 0000000..dec06fa
Binary files /dev/null and b/doccs/site/public/screenshots/user-email.png differ
diff --git a/doccs/site/public/screenshots/user-files.png b/doccs/site/public/screenshots/user-files.png
new file mode 100644
index 0000000..dd27c60
Binary files /dev/null and b/doccs/site/public/screenshots/user-files.png differ
diff --git a/doccs/site/public/screenshots/user-git-deployment.png b/doccs/site/public/screenshots/user-git-deployment.png
new file mode 100644
index 0000000..30e80a5
Binary files /dev/null and b/doccs/site/public/screenshots/user-git-deployment.png differ
diff --git a/doccs/site/public/screenshots/user-home.png b/doccs/site/public/screenshots/user-home.png
new file mode 100644
index 0000000..3a6a106
Binary files /dev/null and b/doccs/site/public/screenshots/user-home.png differ
diff --git a/doccs/site/public/screenshots/user-image-optimization.png b/doccs/site/public/screenshots/user-image-optimization.png
new file mode 100644
index 0000000..41274ea
Binary files /dev/null and b/doccs/site/public/screenshots/user-image-optimization.png differ
diff --git a/doccs/site/public/screenshots/user-login.png b/doccs/site/public/screenshots/user-login.png
new file mode 100644
index 0000000..4d10057
Binary files /dev/null and b/doccs/site/public/screenshots/user-login.png differ
diff --git a/doccs/site/public/screenshots/user-logs--tab-activity-log.png b/doccs/site/public/screenshots/user-logs--tab-activity-log.png
new file mode 100644
index 0000000..ef5ef0f
Binary files /dev/null and b/doccs/site/public/screenshots/user-logs--tab-activity-log.png differ
diff --git a/doccs/site/public/screenshots/user-logs--tab-logs.png b/doccs/site/public/screenshots/user-logs--tab-logs.png
new file mode 100644
index 0000000..5a58df0
Binary files /dev/null and b/doccs/site/public/screenshots/user-logs--tab-logs.png differ
diff --git a/doccs/site/public/screenshots/user-logs--tab-statistics.png b/doccs/site/public/screenshots/user-logs--tab-statistics.png
new file mode 100644
index 0000000..a66cd0e
Binary files /dev/null and b/doccs/site/public/screenshots/user-logs--tab-statistics.png differ
diff --git a/doccs/site/public/screenshots/user-logs.png b/doccs/site/public/screenshots/user-logs.png
new file mode 100644
index 0000000..5a58df0
Binary files /dev/null and b/doccs/site/public/screenshots/user-logs.png differ
diff --git a/doccs/site/public/screenshots/user-mailing-lists.png b/doccs/site/public/screenshots/user-mailing-lists.png
new file mode 100644
index 0000000..7fd4532
Binary files /dev/null and b/doccs/site/public/screenshots/user-mailing-lists.png differ
diff --git a/doccs/site/public/screenshots/user-password-reset-request.png b/doccs/site/public/screenshots/user-password-reset-request.png
new file mode 100644
index 0000000..749a30f
Binary files /dev/null and b/doccs/site/public/screenshots/user-password-reset-request.png differ
diff --git a/doccs/site/public/screenshots/user-password-reset-reset.png b/doccs/site/public/screenshots/user-password-reset-reset.png
new file mode 100644
index 0000000..4f44da7
Binary files /dev/null and b/doccs/site/public/screenshots/user-password-reset-reset.png differ
diff --git a/doccs/site/public/screenshots/user-php-settings.png b/doccs/site/public/screenshots/user-php-settings.png
new file mode 100644
index 0000000..1b598ce
Binary files /dev/null and b/doccs/site/public/screenshots/user-php-settings.png differ
diff --git a/doccs/site/public/screenshots/user-postgresql--tab-databases.png b/doccs/site/public/screenshots/user-postgresql--tab-databases.png
new file mode 100644
index 0000000..2b693cb
Binary files /dev/null and b/doccs/site/public/screenshots/user-postgresql--tab-databases.png differ
diff --git a/doccs/site/public/screenshots/user-postgresql--tab-users.png b/doccs/site/public/screenshots/user-postgresql--tab-users.png
new file mode 100644
index 0000000..b2626e0
Binary files /dev/null and b/doccs/site/public/screenshots/user-postgresql--tab-users.png differ
diff --git a/doccs/site/public/screenshots/user-postgresql.png b/doccs/site/public/screenshots/user-postgresql.png
new file mode 100644
index 0000000..2b693cb
Binary files /dev/null and b/doccs/site/public/screenshots/user-postgresql.png differ
diff --git a/doccs/site/public/screenshots/user-profile.png b/doccs/site/public/screenshots/user-profile.png
new file mode 100644
index 0000000..7a9113a
Binary files /dev/null and b/doccs/site/public/screenshots/user-profile.png differ
diff --git a/doccs/site/public/screenshots/user-protected-directories.png b/doccs/site/public/screenshots/user-protected-directories.png
new file mode 100644
index 0000000..6c15adf
Binary files /dev/null and b/doccs/site/public/screenshots/user-protected-directories.png differ
diff --git a/doccs/site/public/screenshots/user-ssh-keys.png b/doccs/site/public/screenshots/user-ssh-keys.png
new file mode 100644
index 0000000..0f4c67f
Binary files /dev/null and b/doccs/site/public/screenshots/user-ssh-keys.png differ
diff --git a/doccs/site/public/screenshots/user-ssl.png b/doccs/site/public/screenshots/user-ssl.png
new file mode 100644
index 0000000..7f45a91
Binary files /dev/null and b/doccs/site/public/screenshots/user-ssl.png differ
diff --git a/doccs/site/public/screenshots/user-two-factor-challenge.png b/doccs/site/public/screenshots/user-two-factor-challenge.png
new file mode 100644
index 0000000..15481ec
Binary files /dev/null and b/doccs/site/public/screenshots/user-two-factor-challenge.png differ
diff --git a/doccs/site/public/screenshots/user-wordpress.png b/doccs/site/public/screenshots/user-wordpress.png
new file mode 100644
index 0000000..dcc8b2f
Binary files /dev/null and b/doccs/site/public/screenshots/user-wordpress.png differ
diff --git a/doccs/site/src/assets/houston.webp b/doccs/site/src/assets/houston.webp
new file mode 100644
index 0000000..930c164
Binary files /dev/null and b/doccs/site/src/assets/houston.webp differ
diff --git a/doccs/site/src/content.config.ts b/doccs/site/src/content.config.ts
new file mode 100644
index 0000000..d9ee8c9
--- /dev/null
+++ b/doccs/site/src/content.config.ts
@@ -0,0 +1,7 @@
+import { defineCollection } from 'astro:content';
+import { docsLoader } from '@astrojs/starlight/loaders';
+import { docsSchema } from '@astrojs/starlight/schema';
+
+export const collections = {
+ docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
+};
diff --git a/doccs/site/src/content/docs/admin/automation-api.md b/doccs/site/src/content/docs/admin/automation-api.md
new file mode 100644
index 0000000..e61581e
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/automation-api.md
@@ -0,0 +1,21 @@
+---
+title: Api Access
+description: Api Access page details, screenshots, and usage examples.
+---
+
+This page provides api access features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides api access features for the admin panel.
+- Use api access to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use api access to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/backup-download.md b/doccs/site/src/content/docs/admin/backup-download.md
new file mode 100644
index 0000000..5a38d07
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/backup-download.md
@@ -0,0 +1,21 @@
+---
+title: Backup Download
+description: Backup Download page details, screenshots, and usage examples.
+---
+
+This page provides backup download features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides backup download features for the admin panel.
+- Use backup download to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use backup download to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/backups.md b/doccs/site/src/content/docs/admin/backups.md
new file mode 100644
index 0000000..5f236cc
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/backups.md
@@ -0,0 +1,55 @@
+---
+title: Backups
+description: Backups page details, screenshots, and usage examples.
+---
+
+Manage backup destinations, schedules, and backup history in one place.
+
+## Screenshot
+
+
+
+## What this page does
+
+- Manage backup destinations, schedules, and backup history in one place.
+- Create a daily schedule with remote storage.
+- Verify backups weekly using the restore flow.
+
+## Typical examples
+
+- Example 1: Create a daily schedule with remote storage.
+- Example 2: Verify backups weekly using the restore flow.
+
+## Tabs
+
+This page contains tabs. Each tab is captured and explained below.
+
+### Destinations
+
+Remote and local backup targets.
+
+
+
+Example:
+
+- Review destinations settings during onboarding or troubleshooting.
+
+### Schedules
+
+Backup schedule configuration and retention.
+
+
+
+Example:
+
+- Review schedules settings during onboarding or troubleshooting.
+
+### Backups
+
+Backup history and run logs.
+
+
+
+Example:
+
+- Review backups settings during onboarding or troubleshooting.
diff --git a/doccs/site/src/content/docs/admin/cpanel-migration.md b/doccs/site/src/content/docs/admin/cpanel-migration.md
new file mode 100644
index 0000000..45494fd
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/cpanel-migration.md
@@ -0,0 +1,75 @@
+---
+title: Cpanel Migration
+description: Cpanel Migration page details, screenshots, and usage examples.
+---
+
+This page provides cpanel migration features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides cpanel migration features for the admin panel.
+- Use cpanel migration to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use cpanel migration to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
+
+## Tabs
+
+This page contains tabs. Each tab is captured and explained below.
+
+### Domains
+
+Imported domain list from cPanel.
+
+
+
+Example:
+
+- Review domains settings during onboarding or troubleshooting.
+
+### Databases
+
+Imported database list from cPanel.
+
+
+
+Example:
+
+- Review databases settings during onboarding or troubleshooting.
+
+### Mailboxes
+
+Imported mailbox list from cPanel.
+
+
+
+Example:
+
+- Review mailboxes settings during onboarding or troubleshooting.
+
+### Forwarders
+
+Imported forwarders from cPanel.
+
+
+
+Example:
+
+- Review forwarders settings during onboarding or troubleshooting.
+
+### SSL
+
+Imported SSL assets from cPanel.
+
+
+
+Example:
+
+- Review ssl settings during onboarding or troubleshooting.
diff --git a/doccs/site/src/content/docs/admin/dashboard.md b/doccs/site/src/content/docs/admin/dashboard.md
new file mode 100644
index 0000000..751c39a
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/dashboard.md
@@ -0,0 +1,21 @@
+---
+title: Dashboard
+description: Dashboard page details, screenshots, and usage examples.
+---
+
+This dashboard summarizes key activity and server status for quick checks.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This dashboard summarizes key activity and server status for quick checks.
+- Review health cards and activity to confirm the server is stable.
+- Use refresh to re-poll stats after maintenance.
+
+## Typical examples
+
+- Example 1: Review health cards and activity to confirm the server is stable.
+- Example 2: Use refresh to re-poll stats after maintenance.
diff --git a/doccs/site/src/content/docs/admin/database-tuning.md b/doccs/site/src/content/docs/admin/database-tuning.md
new file mode 100644
index 0000000..eced0d4
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/database-tuning.md
@@ -0,0 +1,21 @@
+---
+title: Database Tuning
+description: Database Tuning page details, screenshots, and usage examples.
+---
+
+This page provides database tuning features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides database tuning features for the admin panel.
+- Use database tuning to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use database tuning to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/dns-zones.md b/doccs/site/src/content/docs/admin/dns-zones.md
new file mode 100644
index 0000000..040736d
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/dns-zones.md
@@ -0,0 +1,21 @@
+---
+title: Dns Zones
+description: Dns Zones page details, screenshots, and usage examples.
+---
+
+This page provides dns zones features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides dns zones features for the admin panel.
+- Use dns zones to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use dns zones to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/email-logs.md b/doccs/site/src/content/docs/admin/email-logs.md
new file mode 100644
index 0000000..976911e
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/email-logs.md
@@ -0,0 +1,21 @@
+---
+title: Email Logs
+description: Email Logs page details, screenshots, and usage examples.
+---
+
+This page provides email logs features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides email logs features for the admin panel.
+- Use email logs to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use email logs to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/email-queue.md b/doccs/site/src/content/docs/admin/email-queue.md
new file mode 100644
index 0000000..e4ca1e7
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/email-queue.md
@@ -0,0 +1,21 @@
+---
+title: Email Queue
+description: Email Queue page details, screenshots, and usage examples.
+---
+
+This page provides email queue features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides email queue features for the admin panel.
+- Use email queue to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use email queue to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/geo-block-rules-create.md b/doccs/site/src/content/docs/admin/geo-block-rules-create.md
new file mode 100644
index 0000000..dfdcce9
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/geo-block-rules-create.md
@@ -0,0 +1,21 @@
+---
+title: Jabali-Admin/Geo-Block-Rules/Create
+description: Jabali-Admin/Geo-Block-Rules/Create page details, screenshots, and usage examples.
+---
+
+This page provides jabali-admin/geo-block-rules/create features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides jabali-admin/geo-block-rules/create features for the admin panel.
+- Use jabali-admin/geo-block-rules/create to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use jabali-admin/geo-block-rules/create to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/geo-block-rules-edit.md b/doccs/site/src/content/docs/admin/geo-block-rules-edit.md
new file mode 100644
index 0000000..22d726d
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/geo-block-rules-edit.md
@@ -0,0 +1,21 @@
+---
+title: Jabali-Admin/Geo-Block-Rules/{Record}/Edit
+description: Jabali-Admin/Geo-Block-Rules/{Record}/Edit page details, screenshots, and usage examples.
+---
+
+This page provides jabali-admin/geo-block-rules/{record}/edit features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides jabali-admin/geo-block-rules/{record}/edit features for the admin panel.
+- Use jabali-admin/geo-block-rules/{record}/edit to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use jabali-admin/geo-block-rules/{record}/edit to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/geo-block-rules.md b/doccs/site/src/content/docs/admin/geo-block-rules.md
new file mode 100644
index 0000000..05f883c
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/geo-block-rules.md
@@ -0,0 +1,21 @@
+---
+title: Jabali-Admin/Geo-Block-Rules
+description: Jabali-Admin/Geo-Block-Rules page details, screenshots, and usage examples.
+---
+
+This page provides jabali-admin/geo-block-rules features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides jabali-admin/geo-block-rules features for the admin panel.
+- Use jabali-admin/geo-block-rules to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use jabali-admin/geo-block-rules to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/home.md b/doccs/site/src/content/docs/admin/home.md
new file mode 100644
index 0000000..ab132a5
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/home.md
@@ -0,0 +1,21 @@
+---
+title: Home
+description: Home page details, screenshots, and usage examples.
+---
+
+This page provides home features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides home features for the admin panel.
+- Use home to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use home to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/hosting-packages-create.md b/doccs/site/src/content/docs/admin/hosting-packages-create.md
new file mode 100644
index 0000000..1428018
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/hosting-packages-create.md
@@ -0,0 +1,21 @@
+---
+title: Jabali-Admin/Hosting-Packages/Create
+description: Jabali-Admin/Hosting-Packages/Create page details, screenshots, and usage examples.
+---
+
+This page provides jabali-admin/hosting-packages/create features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides jabali-admin/hosting-packages/create features for the admin panel.
+- Use jabali-admin/hosting-packages/create to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use jabali-admin/hosting-packages/create to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/hosting-packages-edit.md b/doccs/site/src/content/docs/admin/hosting-packages-edit.md
new file mode 100644
index 0000000..699f8bc
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/hosting-packages-edit.md
@@ -0,0 +1,21 @@
+---
+title: Jabali-Admin/Hosting-Packages/{Record}/Edit
+description: Jabali-Admin/Hosting-Packages/{Record}/Edit page details, screenshots, and usage examples.
+---
+
+This page provides jabali-admin/hosting-packages/{record}/edit features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides jabali-admin/hosting-packages/{record}/edit features for the admin panel.
+- Use jabali-admin/hosting-packages/{record}/edit to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use jabali-admin/hosting-packages/{record}/edit to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/hosting-packages.md b/doccs/site/src/content/docs/admin/hosting-packages.md
new file mode 100644
index 0000000..4979838
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/hosting-packages.md
@@ -0,0 +1,21 @@
+---
+title: Jabali-Admin/Hosting-Packages
+description: Jabali-Admin/Hosting-Packages page details, screenshots, and usage examples.
+---
+
+This page provides jabali-admin/hosting-packages features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides jabali-admin/hosting-packages features for the admin panel.
+- Use jabali-admin/hosting-packages to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use jabali-admin/hosting-packages to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/index.md b/doccs/site/src/content/docs/admin/index.md
new file mode 100644
index 0000000..08e87ce
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/index.md
@@ -0,0 +1,18 @@
+---
+title: Admin Panel
+description: Admin panel features and screenshots.
+sidebar:
+ order: 1
+---
+
+The admin panel is the control center for server-wide management. It is designed for hosting providers and server administrators who need full visibility into services, users, security, and system health.
+
+## What you can do here
+
+- Monitor server health and performance
+- Manage users, domains, and quotas
+- Configure DNS and mail services
+- Manage backups and restores
+- Review security posture and service status
+
+Each page below includes an up-to-date screenshot and a short explanation of the feature set.
diff --git a/doccs/site/src/content/docs/admin/ip-addresses.md b/doccs/site/src/content/docs/admin/ip-addresses.md
new file mode 100644
index 0000000..d92c33a
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/ip-addresses.md
@@ -0,0 +1,21 @@
+---
+title: Ip Addresses
+description: Ip Addresses page details, screenshots, and usage examples.
+---
+
+This page provides ip addresses features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides ip addresses features for the admin panel.
+- Use ip addresses to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use ip addresses to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/login.md b/doccs/site/src/content/docs/admin/login.md
new file mode 100644
index 0000000..d8dba11
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/login.md
@@ -0,0 +1,21 @@
+---
+title: Login
+description: Login page details, screenshots, and usage examples.
+---
+
+This page provides login features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides login features for the admin panel.
+- Use login to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use login to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/migration.md b/doccs/site/src/content/docs/admin/migration.md
new file mode 100644
index 0000000..c10d65b
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/migration.md
@@ -0,0 +1,45 @@
+---
+title: Migration
+description: Migration page details, screenshots, and usage examples.
+---
+
+This page provides migration features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides migration features for the admin panel.
+- Use migration to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use migration to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
+
+## Tabs
+
+This page contains tabs. Each tab is captured and explained below.
+
+### cPanel Migration
+
+cPanel migration workflow.
+
+
+
+Example:
+
+- Review cpanel migration settings during onboarding or troubleshooting.
+
+### WHM Migration
+
+WHM migration workflow.
+
+
+
+Example:
+
+- Review whm migration settings during onboarding or troubleshooting.
diff --git a/doccs/site/src/content/docs/admin/password-reset-request.md b/doccs/site/src/content/docs/admin/password-reset-request.md
new file mode 100644
index 0000000..e96b695
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/password-reset-request.md
@@ -0,0 +1,21 @@
+---
+title: Password Reset Request
+description: Password Reset Request page details, screenshots, and usage examples.
+---
+
+This page provides password reset request features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides password reset request features for the admin panel.
+- Use password reset request to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use password reset request to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/password-reset-reset.md b/doccs/site/src/content/docs/admin/password-reset-reset.md
new file mode 100644
index 0000000..757376f
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/password-reset-reset.md
@@ -0,0 +1,21 @@
+---
+title: Password Reset
+description: Password Reset page details, screenshots, and usage examples.
+---
+
+This page provides password reset features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides password reset features for the admin panel.
+- Use password reset to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use password reset to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/php-manager.md b/doccs/site/src/content/docs/admin/php-manager.md
new file mode 100644
index 0000000..d2994fd
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/php-manager.md
@@ -0,0 +1,21 @@
+---
+title: Php Manager
+description: Php Manager page details, screenshots, and usage examples.
+---
+
+This page provides php manager features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides php manager features for the admin panel.
+- Use php manager to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use php manager to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/security.md b/doccs/site/src/content/docs/admin/security.md
new file mode 100644
index 0000000..6c70ae4
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/security.md
@@ -0,0 +1,95 @@
+---
+title: Security
+description: Security page details, screenshots, and usage examples.
+---
+
+Security center for firewall, WAF, scanning, and SSH access control.
+
+## Screenshot
+
+
+
+## What this page does
+
+- Security center for firewall, WAF, scanning, and SSH access control.
+- Review firewall rules after adding new services.
+- Run vulnerability scans after major updates.
+
+## Typical examples
+
+- Example 1: Review firewall rules after adding new services.
+- Example 2: Run vulnerability scans after major updates.
+
+## Tabs
+
+This page contains tabs. Each tab is captured and explained below.
+
+### Overview
+
+Security summary with recent events.
+
+
+
+Example:
+
+- Review overview settings during onboarding or troubleshooting.
+
+### Firewall
+
+UFW rules and port access control.
+
+
+
+Example:
+
+- Review firewall settings during onboarding or troubleshooting.
+
+### ModSecurity / WAF
+
+WAF rules, logs, and request filtering.
+
+
+
+Example:
+
+- Review modsecurity / waf settings during onboarding or troubleshooting.
+
+### Fail2ban
+
+Login protection and jail settings.
+
+
+
+Example:
+
+- Review fail2ban settings during onboarding or troubleshooting.
+
+### Antivirus
+
+ClamAV status and scan controls.
+
+
+
+Example:
+
+- Review antivirus settings during onboarding or troubleshooting.
+
+### SSH
+
+SSH access settings and recent logins.
+
+
+
+Example:
+
+- Review ssh settings during onboarding or troubleshooting.
+
+### Vulnerability Scanner
+
+Scan results and remediation guidance.
+
+
+
+Example:
+
+- Review vulnerability scanner settings during onboarding or troubleshooting.
diff --git a/doccs/site/src/content/docs/admin/server-settings.md b/doccs/site/src/content/docs/admin/server-settings.md
new file mode 100644
index 0000000..e1e264b
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/server-settings.md
@@ -0,0 +1,95 @@
+---
+title: Server Settings
+description: Server Settings page details, screenshots, and usage examples.
+---
+
+Central configuration for global DNS, storage, notifications, and runtime defaults.
+
+## Screenshot
+
+
+
+## What this page does
+
+- Central configuration for global DNS, storage, notifications, and runtime defaults.
+- Add notification recipients before production go-live.
+- Tune PHP-FPM defaults if performance needs adjustment.
+
+## Typical examples
+
+- Example 1: Add notification recipients before production go-live.
+- Example 2: Tune PHP-FPM defaults if performance needs adjustment.
+
+## Tabs
+
+This page contains tabs. Each tab is captured and explained below.
+
+### General
+
+Base panel identity, system defaults, and global settings.
+
+
+
+Example:
+
+- Review general settings during onboarding or troubleshooting.
+
+### DNS
+
+Nameserver and DNS behavior configuration.
+
+
+
+Example:
+
+- Review dns settings during onboarding or troubleshooting.
+
+### Storage
+
+Disk and backup storage settings.
+
+
+
+Example:
+
+- Review storage settings during onboarding or troubleshooting.
+
+### Email
+
+Mail defaults and system mail configuration.
+
+
+
+Example:
+
+- Review email settings during onboarding or troubleshooting.
+
+### Notifications
+
+Alert destinations, thresholds, and notification toggles.
+
+
+
+Example:
+
+- Review notifications settings during onboarding or troubleshooting.
+
+### PHP-FPM
+
+Runtime defaults for PHP-FPM pools and limits.
+
+
+
+Example:
+
+- Review php-fpm settings during onboarding or troubleshooting.
+
+### Database Tuning
+
+MariaDB and database performance parameters.
+
+
+
+Example:
+
+- Review database tuning settings during onboarding or troubleshooting.
diff --git a/doccs/site/src/content/docs/admin/server-status.md b/doccs/site/src/content/docs/admin/server-status.md
new file mode 100644
index 0000000..3c2f8fb
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/server-status.md
@@ -0,0 +1,21 @@
+---
+title: Server Status
+description: Server Status page details, screenshots, and usage examples.
+---
+
+Live charts and service indicators help diagnose resource or service issues.
+
+## Screenshot
+
+
+
+## What this page does
+
+- Live charts and service indicators help diagnose resource or service issues.
+- Check CPU and memory trends when users report slowness.
+- Verify service status after restarts or upgrades.
+
+## Typical examples
+
+- Example 1: Check CPU and memory trends when users report slowness.
+- Example 2: Verify service status after restarts or upgrades.
diff --git a/doccs/site/src/content/docs/admin/server-updates.md b/doccs/site/src/content/docs/admin/server-updates.md
new file mode 100644
index 0000000..885d3dd
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/server-updates.md
@@ -0,0 +1,21 @@
+---
+title: System Updates
+description: System Updates page details, screenshots, and usage examples.
+---
+
+This page provides system updates features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides system updates features for the admin panel.
+- Use system updates to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use system updates to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/services.md b/doccs/site/src/content/docs/admin/services.md
new file mode 100644
index 0000000..e927d98
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/services.md
@@ -0,0 +1,21 @@
+---
+title: Services
+description: Services page details, screenshots, and usage examples.
+---
+
+This page provides services features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides services features for the admin panel.
+- Use services to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use services to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/ssl-manager.md b/doccs/site/src/content/docs/admin/ssl-manager.md
new file mode 100644
index 0000000..7b5cb4c
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/ssl-manager.md
@@ -0,0 +1,21 @@
+---
+title: Ssl Manager
+description: Ssl Manager page details, screenshots, and usage examples.
+---
+
+This page provides ssl manager features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides ssl manager features for the admin panel.
+- Use ssl manager to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use ssl manager to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/two-factor-challenge.md b/doccs/site/src/content/docs/admin/two-factor-challenge.md
new file mode 100644
index 0000000..1a5e742
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/two-factor-challenge.md
@@ -0,0 +1,21 @@
+---
+title: Two-Factor Challenge
+description: Two-Factor Challenge page details, screenshots, and usage examples.
+---
+
+This page provides two-factor challenge features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides two-factor challenge features for the admin panel.
+- Use two-factor challenge to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use two-factor challenge to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/users-create.md b/doccs/site/src/content/docs/admin/users-create.md
new file mode 100644
index 0000000..8b64e08
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/users-create.md
@@ -0,0 +1,21 @@
+---
+title: Jabali-Admin/Users/Create
+description: Jabali-Admin/Users/Create page details, screenshots, and usage examples.
+---
+
+This page provides jabali-admin/users/create features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides jabali-admin/users/create features for the admin panel.
+- Use jabali-admin/users/create to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use jabali-admin/users/create to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/users-edit.md b/doccs/site/src/content/docs/admin/users-edit.md
new file mode 100644
index 0000000..106f8dd
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/users-edit.md
@@ -0,0 +1,21 @@
+---
+title: Jabali-Admin/Users/{Record}/Edit
+description: Jabali-Admin/Users/{Record}/Edit page details, screenshots, and usage examples.
+---
+
+This page provides jabali-admin/users/{record}/edit features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides jabali-admin/users/{record}/edit features for the admin panel.
+- Use jabali-admin/users/{record}/edit to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use jabali-admin/users/{record}/edit to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/users.md b/doccs/site/src/content/docs/admin/users.md
new file mode 100644
index 0000000..2a83cdc
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/users.md
@@ -0,0 +1,21 @@
+---
+title: Jabali-Admin/Users
+description: Jabali-Admin/Users page details, screenshots, and usage examples.
+---
+
+This page provides jabali-admin/users features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides jabali-admin/users features for the admin panel.
+- Use jabali-admin/users to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use jabali-admin/users to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/waf.md b/doccs/site/src/content/docs/admin/waf.md
new file mode 100644
index 0000000..711c7b3
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/waf.md
@@ -0,0 +1,21 @@
+---
+title: Modsecurity / Waf
+description: Modsecurity / Waf page details, screenshots, and usage examples.
+---
+
+This page provides modsecurity / waf features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides modsecurity / waf features for the admin panel.
+- Use modsecurity / waf to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use modsecurity / waf to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/webhook-endpoints-create.md b/doccs/site/src/content/docs/admin/webhook-endpoints-create.md
new file mode 100644
index 0000000..0612dbe
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/webhook-endpoints-create.md
@@ -0,0 +1,21 @@
+---
+title: Jabali-Admin/Webhook-Endpoints/Create
+description: Jabali-Admin/Webhook-Endpoints/Create page details, screenshots, and usage examples.
+---
+
+This page provides jabali-admin/webhook-endpoints/create features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides jabali-admin/webhook-endpoints/create features for the admin panel.
+- Use jabali-admin/webhook-endpoints/create to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use jabali-admin/webhook-endpoints/create to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/webhook-endpoints-edit.md b/doccs/site/src/content/docs/admin/webhook-endpoints-edit.md
new file mode 100644
index 0000000..8fc7082
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/webhook-endpoints-edit.md
@@ -0,0 +1,21 @@
+---
+title: Jabali-Admin/Webhook-Endpoints/{Record}/Edit
+description: Jabali-Admin/Webhook-Endpoints/{Record}/Edit page details, screenshots, and usage examples.
+---
+
+This page provides jabali-admin/webhook-endpoints/{record}/edit features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides jabali-admin/webhook-endpoints/{record}/edit features for the admin panel.
+- Use jabali-admin/webhook-endpoints/{record}/edit to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use jabali-admin/webhook-endpoints/{record}/edit to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/webhook-endpoints.md b/doccs/site/src/content/docs/admin/webhook-endpoints.md
new file mode 100644
index 0000000..f659631
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/webhook-endpoints.md
@@ -0,0 +1,21 @@
+---
+title: Jabali-Admin/Webhook-Endpoints
+description: Jabali-Admin/Webhook-Endpoints page details, screenshots, and usage examples.
+---
+
+This page provides jabali-admin/webhook-endpoints features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides jabali-admin/webhook-endpoints features for the admin panel.
+- Use jabali-admin/webhook-endpoints to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use jabali-admin/webhook-endpoints to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/admin/whm-migration.md b/doccs/site/src/content/docs/admin/whm-migration.md
new file mode 100644
index 0000000..57b9862
--- /dev/null
+++ b/doccs/site/src/content/docs/admin/whm-migration.md
@@ -0,0 +1,21 @@
+---
+title: Whm Migration
+description: Whm Migration page details, screenshots, and usage examples.
+---
+
+This page provides whm migration features for the admin panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides whm migration features for the admin panel.
+- Use whm migration to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use whm migration to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/index.mdx b/doccs/site/src/content/docs/index.mdx
new file mode 100644
index 0000000..eccc37f
--- /dev/null
+++ b/doccs/site/src/content/docs/index.mdx
@@ -0,0 +1,37 @@
+---
+title: Jabali Panel Documentation
+description: Feature overview and screenshots for the Jabali hosting panel.
+---
+
+Welcome to the Jabali Panel documentation site. This site focuses on product features and provides up-to-date screenshots for both the admin and user panels.
+
+## Start here
+
+- Read the [Overview](/overview) for a quick product tour.
+- Browse the [Admin Panel](/admin/dashboard) features.
+- Browse the [User Panel](/user/dashboard) features.
+- Learn about platform services under [Platform](/platform/stack).
+
+## Feature highlights
+
+### Admin panel
+
+
+
+### User panel
+
+
+
+## Screenshot library
+
+All screenshots are generated from the live panel using the repo script:
+
+~~~
+node tests/take-screenshots.cjs --output-dir=docs/screenshots
+~~~
+
+The documentation site uses a copy of those images at:
+
+~~~
+/var/www/jabali/doccs/site/public/screenshots
+~~~
diff --git a/doccs/site/src/content/docs/overview.md b/doccs/site/src/content/docs/overview.md
new file mode 100644
index 0000000..e2b9a4d
--- /dev/null
+++ b/doccs/site/src/content/docs/overview.md
@@ -0,0 +1,32 @@
+---
+title: Overview
+description: Product overview, panels, and key services.
+sidebar:
+ order: 1
+---
+
+Jabali is a modern hosting control panel for WordPress and general PHP hosting. It combines a user-friendly interface with a privileged agent to perform system operations safely and consistently.
+
+## Panels
+
+- **Admin panel** (/jabali-admin): server-wide management, service health, security, backups, and global settings.
+- **User panel** (/jabali-panel): per-account hosting tasks like domains, email, databases, and backups.
+
+## Core ideas
+
+- **Automation-first**: UI actions map to reliable backend jobs.
+- **Isolation**: each user is isolated at the OS and service level.
+- **Observability**: health checks, logs, and notifications are built in.
+- **Consistency**: the agent applies changes using repeatable, auditable steps.
+
+## Where to find screenshots
+
+- Admin features: [Admin Panel](/admin/dashboard)
+- User features: [User Panel](/user/dashboard)
+- Platform services: [Platform](/platform/stack)
+
+## Typical workflows
+
+- **New server setup**: verify services, configure DNS and mail, set alerting.
+- **Onboard user**: create user, set quotas, add domains, issue SSL.
+- **Routine operations**: review health, run backups, rotate credentials.
diff --git a/doccs/site/src/content/docs/platform/agent.md b/doccs/site/src/content/docs/platform/agent.md
new file mode 100644
index 0000000..f46cb9a
--- /dev/null
+++ b/doccs/site/src/content/docs/platform/agent.md
@@ -0,0 +1,27 @@
+---
+title: Privileged Agent
+description: Root-level automation for system tasks.
+sidebar:
+ order: 2
+---
+
+The jabali-agent daemon runs as root and executes system-level tasks that cannot be safely handled by the web app alone.
+
+## Responsibilities
+
+- System user creation and deletion
+- Vhost and PHP-FPM pool configuration
+- SSL certificate issuance and renewal
+- DNS zone updates
+- Mail domain and mailbox operations
+- Backup and restore workflows
+
+## Why it exists
+
+- Ensures privileged operations are centralized and auditable
+- Reduces direct root access requirements in the UI
+- Allows consistent, repeatable system changes
+
+## Communication
+
+- The panel communicates with the agent over a local Unix socket at /var/run/jabali/agent.sock.
diff --git a/doccs/site/src/content/docs/platform/backups.md b/doccs/site/src/content/docs/platform/backups.md
new file mode 100644
index 0000000..7fb127f
--- /dev/null
+++ b/doccs/site/src/content/docs/platform/backups.md
@@ -0,0 +1,28 @@
+---
+title: Backup System
+description: Local and remote backups with restore options.
+sidebar:
+ order: 4
+---
+
+Backups are available for individual users and for the full server. They include files, databases, mail, and configuration data.
+
+## Backup types
+
+- User backups stored under /home//backups
+- Server backups stored under /var/backups/jabali
+- Incremental backups to remote targets
+
+## Restore coverage
+
+- Website files
+- Databases and users
+- Mailboxes
+- SSL certificates
+- DNS zone files
+
+## Best practices
+
+- Keep at least one remote destination
+- Test restores on a schedule
+- Maintain retention policies to save storage
diff --git a/doccs/site/src/content/docs/platform/cli.md b/doccs/site/src/content/docs/platform/cli.md
new file mode 100644
index 0000000..6e7d6b1
--- /dev/null
+++ b/doccs/site/src/content/docs/platform/cli.md
@@ -0,0 +1,308 @@
+---
+title: Jabali CLI
+description: Full command reference with options and examples.
+sidebar:
+ order: 6
+---
+
+The Jabali CLI is a full-featured administrative interface to the panel and the privileged agent. Use it for automation, server tasks, backups, migrations, and operational maintenance.
+
+## Run location
+
+Run all commands from the repo root:
+
+~~~
+cd /var/www/jabali
+~~~
+
+## Global help and options
+
+~~~
+jabali --help
+jabali --help-full
+jabali --version
+~~~
+
+Global options:
+
+- `-h`, `--help` show help
+- `--help-full` show full command list
+- `-v`, `--version` show version
+- `-y`, `--yes` auto-confirm prompts
+- `-q`, `--quiet` quiet mode
+
+## User management
+
+Commands:
+
+~~~
+jabali user list
+jabali user create [--email=] [--password=]
+jabali user show
+jabali user delete
+jabali user password [--password=]
+jabali user suspend
+jabali user unsuspend
+~~~
+
+Notes:
+
+- `user create` creates a system user through the agent and a panel user in the database.
+- `user password` updates both the panel password and system user password.
+
+## Domain management
+
+Commands:
+
+~~~
+jabali domain list [--user=]
+jabali domain create --user=
+jabali domain show
+jabali domain delete
+jabali domain enable
+jabali domain disable
+~~~
+
+Notes:
+
+- `domain create` triggers agent provisioning and then creates the panel record.
+
+## Service management
+
+Commands:
+
+~~~
+jabali service list
+jabali service status
+jabali service start
+jabali service stop
+jabali service restart
+jabali service enable
+jabali service disable
+~~~
+
+Services include common system daemons and any installed PHP-FPM versions.
+
+## WordPress tools
+
+Commands:
+
+~~~
+jabali wp list
+jabali wp install [--title=] [--admin=] [--email=] [--password=]
+jabali wp scan
+jabali wp import
+jabali wp delete [--files] [--database]
+jabali wp update
+~~~
+
+Notes:
+
+- `wp install` will generate a password if one is not provided.
+- `wp scan` discovers existing WordPress installs under a user.
+
+## Database tools (MariaDB)
+
+Commands:
+
+~~~
+jabali db list [--user=]
+jabali db create [--user=]
+jabali db delete
+jabali db users [--user=]
+jabali db user-create [--password=] [--host=]
+jabali db user-delete [--host=]
+~~~
+
+Notes:
+
+- `db list` defaults to `admin` unless `--user` is provided.
+- User creation validates password complexity if provided.
+
+## Email (mailboxes)
+
+Commands:
+
+~~~
+jabali mail list [--domain=]
+jabali mail create [--password=] [--quota=]
+jabali mail delete
+jabali mail password [--password=]
+jabali mail quota
+jabali mail domains
+~~~
+
+Notes:
+
+- `mail domains` lists domains with mail enabled and DKIM status.
+
+## Backups (users + server)
+
+### Local and user backups
+
+~~~
+jabali backup list [--user=]
+jabali backup user-list
+jabali backup create [--type=full|incremental] [--output=] [--incremental-base=]
+ [--domains=a,b] [--databases=a,b] [--mailboxes=a,b]
+ [--no-files] [--no-databases] [--no-mailboxes] [--no-dns] [--no-ssl]
+
+jabali backup restore []
+ [--user=] [--domains=a,b] [--databases=a,b] [--mailboxes=a,b]
+ [--no-files] [--no-databases] [--no-mailboxes] [--no-dns] [--no-ssl]
+
+jabali backup info
+jabali backup verify
+jabali backup delete [--user=]
+~~~
+
+### Server backups
+
+~~~
+jabali backup server [--type=full|incremental] [--users=u1,u2] [--dest=]
+jabali backup server-list
+~~~
+
+### Backup history (database)
+
+~~~
+jabali backup history [--limit=] [--status=] [--type=]
+jabali backup show
+~~~
+
+### Backup schedules
+
+~~~
+jabali backup schedules
+jabali backup schedule-create --name= [--frequency=daily|weekly] [--time=HH:MM]
+ [--retention=] [--dest=] [--backup-type=full|incremental]
+ [--no-files] [--no-databases] [--no-mailboxes] [--no-dns]
+
+jabali backup schedule-run
+jabali backup schedule-enable
+jabali backup schedule-disable
+jabali backup schedule-delete
+~~~
+
+### Backup destinations
+
+~~~
+jabali backup destinations
+jabali backup dest-add --type=sftp --name= --host= --user= [--password=] [--port=22] [--path=/backups]
+
+jabali backup dest-add --type=nfs --name= --host= --path= [--mount=/mnt/backup]
+
+jabali backup dest-add --type=s3 --name= --bucket= --key= --secret= [--region=us-east-1] [--path=prefix]
+
+jabali backup dest-test
+jabali backup dest-delete
+~~~
+
+## cPanel migration
+
+Commands:
+
+~~~
+jabali cpanel analyze [--timeout=600]
+jabali cpanel restore
+ [--no-files] [--no-databases] [--no-emails] [--no-ssl]
+ [--log=/path/to/log.jsonl] [--analyze] [--timeout=7200]
+
+jabali cpanel fix-permissions
+~~~
+
+Notes:
+
+- `cpanel restore` requires the panel user and the system user to already exist.
+- `--analyze` runs analysis and reuses results before restore.
+
+## System information
+
+Commands:
+
+~~~
+jabali system info
+jabali system status
+jabali system hostname []
+jabali system disk
+jabali system memory
+~~~
+
+## Agent control
+
+Commands:
+
+~~~
+jabali agent status
+jabali agent start
+jabali agent stop
+jabali agent restart
+jabali agent ping
+jabali agent log [--lines=]
+~~~
+
+## PHP versions
+
+Commands:
+
+~~~
+jabali php list
+jabali php install
+jabali php uninstall
+jabali php default []
+jabali php status
+~~~
+
+Notes:
+
+- `php default` without a version prints the current default.
+
+## Firewall (UFW)
+
+Commands:
+
+~~~
+jabali firewall status
+jabali firewall enable
+jabali firewall disable
+jabali firewall rules
+jabali firewall allow
+jabali firewall deny
+jabali firewall delete
+~~~
+
+## SSL certificates
+
+Commands:
+
+~~~
+jabali ssl check [] [--issue-only] [--renew-only]
+jabali ssl issue [--force]
+jabali ssl renew
+jabali ssl status
+jabali ssl list
+~~~
+
+## Example workflows
+
+### Onboard a new user and domain
+
+~~~
+jabali user create demo --email=demo@example.com
+jabali domain create example.com --user=demo
+jabali ssl issue example.com
+~~~
+
+### Create and verify a user backup
+
+~~~
+jabali backup create demo --type=full
+jabali backup verify /home/demo/backups/demo_2026-02-04_120000.tar.gz
+~~~
+
+### Run a cPanel migration
+
+~~~
+jabali cpanel analyze /var/backups/jabali/cpanel-migrations/site.tar.gz
+jabali cpanel restore /var/backups/jabali/cpanel-migrations/site.tar.gz demo
+~~~
diff --git a/doccs/site/src/content/docs/platform/dnssec.md b/doccs/site/src/content/docs/platform/dnssec.md
new file mode 100644
index 0000000..49e2b6b
--- /dev/null
+++ b/doccs/site/src/content/docs/platform/dnssec.md
@@ -0,0 +1,27 @@
+---
+title: DNSSEC
+description: DNSSEC management and DS records.
+sidebar:
+ order: 5
+---
+
+DNSSEC adds cryptographic signatures to DNS records for stronger integrity guarantees.
+
+## What it does
+
+- Signs DNS zones with cryptographic keys
+- Lets resolvers validate responses
+- Reduces risk of DNS spoofing
+
+## Setup flow
+
+1. Enable DNSSEC for a domain
+2. Copy the DS record from the panel
+3. Add the DS record at the registrar
+4. Wait for propagation
+
+## Management tips
+
+- Rotate keys only when necessary
+- Keep DS records in sync with the panel
+- Monitor for DNSSEC validation errors
diff --git a/doccs/site/src/content/docs/platform/index.md b/doccs/site/src/content/docs/platform/index.md
new file mode 100644
index 0000000..c48078d
--- /dev/null
+++ b/doccs/site/src/content/docs/platform/index.md
@@ -0,0 +1,8 @@
+---
+title: Platform
+description: Core services and operational tooling.
+sidebar:
+ order: 1
+---
+
+The platform section covers core services, privileged automation, monitoring, backups, DNSSEC, and the Jabali CLI.
diff --git a/doccs/site/src/content/docs/platform/monitoring.md b/doccs/site/src/content/docs/platform/monitoring.md
new file mode 100644
index 0000000..a2a2c99
--- /dev/null
+++ b/doccs/site/src/content/docs/platform/monitoring.md
@@ -0,0 +1,29 @@
+---
+title: Monitoring and Alerts
+description: Health monitoring, logs, and notifications.
+sidebar:
+ order: 3
+---
+
+Jabali includes a health monitor daemon and a notification system to keep administrators informed.
+
+## Health monitor
+
+- Checks critical services every 30 seconds
+- Attempts automatic restarts on failures
+- Logs events to /var/log/jabali/health-monitor.log
+
+## Alert types
+
+- SSL expiration and errors
+- Backup failures
+- Disk quota warnings
+- Login failures
+- Service health alerts
+- High load notifications
+
+## Operational tips
+
+- Configure alert recipients during initial setup
+- Test the mail sender before relying on alerts
+- Review notification logs during incidents
diff --git a/doccs/site/src/content/docs/platform/stack.md b/doccs/site/src/content/docs/platform/stack.md
new file mode 100644
index 0000000..e018149
--- /dev/null
+++ b/doccs/site/src/content/docs/platform/stack.md
@@ -0,0 +1,28 @@
+---
+title: Platform Stack
+description: Core services and runtime components.
+sidebar:
+ order: 1
+---
+
+Jabali uses a modern Laravel application for the control plane and a privileged agent for system operations.
+
+## Application stack
+
+- Laravel 12 with Filament v5 and Livewire v4
+- Tailwind-based UI
+- SQLite for panel metadata
+
+## Service stack
+
+- Nginx and PHP-FPM
+- MariaDB for user databases
+- Postfix, Dovecot, and Rspamd for mail
+- BIND9 for DNS
+- Redis for cache and queue
+
+## Runtime targets
+
+- Debian 12 or 13
+- PHP 8.4
+- Node 20 and Vite for assets
diff --git a/doccs/site/src/content/docs/user/backup-download.md b/doccs/site/src/content/docs/user/backup-download.md
new file mode 100644
index 0000000..1b0c094
--- /dev/null
+++ b/doccs/site/src/content/docs/user/backup-download.md
@@ -0,0 +1,21 @@
+---
+title: Backup Download
+description: Backup Download page details, screenshots, and usage examples.
+---
+
+This page provides backup download features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides backup download features for the jabali panel.
+- Use backup download to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use backup download to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/user/backups.md b/doccs/site/src/content/docs/user/backups.md
new file mode 100644
index 0000000..5ff1e6e
--- /dev/null
+++ b/doccs/site/src/content/docs/user/backups.md
@@ -0,0 +1,65 @@
+---
+title: Backups
+description: Backups page details, screenshots, and usage examples.
+---
+
+Manage backup destinations, schedules, and backup history in one place.
+
+## Screenshot
+
+
+
+## What this page does
+
+- Manage backup destinations, schedules, and backup history in one place.
+- Create a daily schedule with remote storage.
+- Verify backups weekly using the restore flow.
+
+## Typical examples
+
+- Example 1: Create a daily schedule with remote storage.
+- Example 2: Verify backups weekly using the restore flow.
+
+## Tabs
+
+This page contains tabs. Each tab is captured and explained below.
+
+### My Backups
+
+User-owned backups and restore points.
+
+
+
+Example:
+
+- Review my backups settings during onboarding or troubleshooting.
+
+### Server Backups
+
+Server-level backups available to the user.
+
+
+
+Example:
+
+- Review server backups settings during onboarding or troubleshooting.
+
+### SFTP Destinations
+
+Remote destinations for backups.
+
+
+
+Example:
+
+- Review sftp destinations settings during onboarding or troubleshooting.
+
+### Restore History
+
+Log of recent restore actions.
+
+
+
+Example:
+
+- Review restore history settings during onboarding or troubleshooting.
diff --git a/doccs/site/src/content/docs/user/cdn-integration.md b/doccs/site/src/content/docs/user/cdn-integration.md
new file mode 100644
index 0000000..219fc36
--- /dev/null
+++ b/doccs/site/src/content/docs/user/cdn-integration.md
@@ -0,0 +1,21 @@
+---
+title: Cdn Integration
+description: Cdn Integration page details, screenshots, and usage examples.
+---
+
+This page provides cdn integration features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides cdn integration features for the jabali panel.
+- Use cdn integration to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use cdn integration to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/user/cpanel-migration.md b/doccs/site/src/content/docs/user/cpanel-migration.md
new file mode 100644
index 0000000..2b1f281
--- /dev/null
+++ b/doccs/site/src/content/docs/user/cpanel-migration.md
@@ -0,0 +1,75 @@
+---
+title: Cpanel Migration
+description: Cpanel Migration page details, screenshots, and usage examples.
+---
+
+This page provides cpanel migration features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides cpanel migration features for the jabali panel.
+- Use cpanel migration to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use cpanel migration to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
+
+## Tabs
+
+This page contains tabs. Each tab is captured and explained below.
+
+### Domains
+
+Imported domain list from cPanel.
+
+
+
+Example:
+
+- Review domains settings during onboarding or troubleshooting.
+
+### Databases
+
+Imported database list from cPanel.
+
+
+
+Example:
+
+- Review databases settings during onboarding or troubleshooting.
+
+### Mailboxes
+
+Imported mailbox list from cPanel.
+
+
+
+Example:
+
+- Review mailboxes settings during onboarding or troubleshooting.
+
+### Forwarders
+
+Imported forwarders from cPanel.
+
+
+
+Example:
+
+- Review forwarders settings during onboarding or troubleshooting.
+
+### SSL
+
+Imported SSL assets from cPanel.
+
+
+
+Example:
+
+- Review ssl settings during onboarding or troubleshooting.
diff --git a/doccs/site/src/content/docs/user/cron-jobs.md b/doccs/site/src/content/docs/user/cron-jobs.md
new file mode 100644
index 0000000..d80c067
--- /dev/null
+++ b/doccs/site/src/content/docs/user/cron-jobs.md
@@ -0,0 +1,21 @@
+---
+title: Cron Jobs
+description: Cron Jobs page details, screenshots, and usage examples.
+---
+
+This page provides cron jobs features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides cron jobs features for the jabali panel.
+- Use cron jobs to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use cron jobs to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/user/dashboard.md b/doccs/site/src/content/docs/user/dashboard.md
new file mode 100644
index 0000000..16ca915
--- /dev/null
+++ b/doccs/site/src/content/docs/user/dashboard.md
@@ -0,0 +1,22 @@
+---
+title: Dashboard
+description: User overview of resources and recent activity.
+sidebar:
+ order: 2
+---
+
+The user dashboard is the landing view after login. It summarizes current usage and highlights key actions.
+
+## What you see
+
+- Domain and mailbox counts
+- Database usage
+- SSL coverage summary
+- Recent activity and backups
+
+## Why it matters
+
+- Detect limits before they become a problem
+- Jump into key tasks with fewer clicks
+
+
diff --git a/doccs/site/src/content/docs/user/databases.md b/doccs/site/src/content/docs/user/databases.md
new file mode 100644
index 0000000..0c108c7
--- /dev/null
+++ b/doccs/site/src/content/docs/user/databases.md
@@ -0,0 +1,21 @@
+---
+title: Databases
+description: Databases page details, screenshots, and usage examples.
+---
+
+This page provides databases features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides databases features for the jabali panel.
+- Use databases to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use databases to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/user/dns-records.md b/doccs/site/src/content/docs/user/dns-records.md
new file mode 100644
index 0000000..d7bfc9a
--- /dev/null
+++ b/doccs/site/src/content/docs/user/dns-records.md
@@ -0,0 +1,21 @@
+---
+title: Dns Records
+description: Dns Records page details, screenshots, and usage examples.
+---
+
+This page provides dns records features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides dns records features for the jabali panel.
+- Use dns records to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use dns records to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/user/domains.md b/doccs/site/src/content/docs/user/domains.md
new file mode 100644
index 0000000..aeb9c3e
--- /dev/null
+++ b/doccs/site/src/content/docs/user/domains.md
@@ -0,0 +1,21 @@
+---
+title: Domains
+description: Domains page details, screenshots, and usage examples.
+---
+
+Domain management for hosting sites, SSL, and DNS integration.
+
+## Screenshot
+
+
+
+## What this page does
+
+- Domain management for hosting sites, SSL, and DNS integration.
+- Add a new domain and issue SSL.
+- Set a redirect when decommissioning a site.
+
+## Typical examples
+
+- Example 1: Add a new domain and issue SSL.
+- Example 2: Set a redirect when decommissioning a site.
diff --git a/doccs/site/src/content/docs/user/email.md b/doccs/site/src/content/docs/user/email.md
new file mode 100644
index 0000000..7033acc
--- /dev/null
+++ b/doccs/site/src/content/docs/user/email.md
@@ -0,0 +1,85 @@
+---
+title: Email
+description: Email page details, screenshots, and usage examples.
+---
+
+Email management for domains, mailboxes, and spam controls.
+
+## Screenshot
+
+
+
+## What this page does
+
+- Email management for domains, mailboxes, and spam controls.
+- Create mailboxes for new staff accounts.
+- Adjust spam settings after a deliverability issue.
+
+## Typical examples
+
+- Example 1: Create mailboxes for new staff accounts.
+- Example 2: Adjust spam settings after a deliverability issue.
+
+## Tabs
+
+This page contains tabs. Each tab is captured and explained below.
+
+### Mailboxes
+
+Imported mailbox list from cPanel.
+
+
+
+Example:
+
+- Review mailboxes settings during onboarding or troubleshooting.
+
+### Forwarders
+
+Imported forwarders from cPanel.
+
+
+
+Example:
+
+- Review forwarders settings during onboarding or troubleshooting.
+
+### Autoresponders
+
+Automatic replies for mailboxes.
+
+
+
+Example:
+
+- Review autoresponders settings during onboarding or troubleshooting.
+
+### Catch-All
+
+Domain-wide catch-all routing.
+
+
+
+Example:
+
+- Review catch-all settings during onboarding or troubleshooting.
+
+### Logs
+
+Raw log entries for troubleshooting.
+
+
+
+Example:
+
+- Review logs settings during onboarding or troubleshooting.
+
+### Spam Settings
+
+Spam filtering and scoring.
+
+
+
+Example:
+
+- Review spam settings settings during onboarding or troubleshooting.
diff --git a/doccs/site/src/content/docs/user/files.md b/doccs/site/src/content/docs/user/files.md
new file mode 100644
index 0000000..2064a33
--- /dev/null
+++ b/doccs/site/src/content/docs/user/files.md
@@ -0,0 +1,21 @@
+---
+title: Files
+description: Files page details, screenshots, and usage examples.
+---
+
+This page provides files features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides files features for the jabali panel.
+- Use files to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use files to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/user/git-deployment.md b/doccs/site/src/content/docs/user/git-deployment.md
new file mode 100644
index 0000000..85b83cc
--- /dev/null
+++ b/doccs/site/src/content/docs/user/git-deployment.md
@@ -0,0 +1,21 @@
+---
+title: Git Deployment
+description: Git Deployment page details, screenshots, and usage examples.
+---
+
+This page provides git deployment features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides git deployment features for the jabali panel.
+- Use git deployment to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use git deployment to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/user/home.md b/doccs/site/src/content/docs/user/home.md
new file mode 100644
index 0000000..5234a9c
--- /dev/null
+++ b/doccs/site/src/content/docs/user/home.md
@@ -0,0 +1,21 @@
+---
+title: Dashboard
+description: Dashboard page details, screenshots, and usage examples.
+---
+
+This page provides dashboard features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides dashboard features for the jabali panel.
+- Use dashboard to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use dashboard to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/user/image-optimization.md b/doccs/site/src/content/docs/user/image-optimization.md
new file mode 100644
index 0000000..5da8f5b
--- /dev/null
+++ b/doccs/site/src/content/docs/user/image-optimization.md
@@ -0,0 +1,21 @@
+---
+title: Image Optimization
+description: Image Optimization page details, screenshots, and usage examples.
+---
+
+This page provides image optimization features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides image optimization features for the jabali panel.
+- Use image optimization to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use image optimization to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/user/index.md b/doccs/site/src/content/docs/user/index.md
new file mode 100644
index 0000000..4dc0729
--- /dev/null
+++ b/doccs/site/src/content/docs/user/index.md
@@ -0,0 +1,16 @@
+---
+title: User Panel
+description: User panel features and screenshots.
+sidebar:
+ order: 1
+---
+
+The user panel is designed for everyday hosting tasks. It gives users full control over their domains, email, databases, and backups while keeping the experience simple.
+
+## What users can do
+
+- Add and manage domains
+- Configure DNS records
+- Manage email mailboxes and forwarders
+- Install and maintain WordPress
+- Create backups and restore data
diff --git a/doccs/site/src/content/docs/user/login.md b/doccs/site/src/content/docs/user/login.md
new file mode 100644
index 0000000..c324b6d
--- /dev/null
+++ b/doccs/site/src/content/docs/user/login.md
@@ -0,0 +1,21 @@
+---
+title: Login
+description: Login page details, screenshots, and usage examples.
+---
+
+This page provides login features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides login features for the jabali panel.
+- Use login to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use login to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/user/logs.md b/doccs/site/src/content/docs/user/logs.md
new file mode 100644
index 0000000..051e8b8
--- /dev/null
+++ b/doccs/site/src/content/docs/user/logs.md
@@ -0,0 +1,55 @@
+---
+title: Logs & Statistics
+description: Logs & Statistics page details, screenshots, and usage examples.
+---
+
+This page provides logs & statistics features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides logs & statistics features for the jabali panel.
+- Use logs & statistics to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use logs & statistics to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
+
+## Tabs
+
+This page contains tabs. Each tab is captured and explained below.
+
+### Logs
+
+Raw log entries for troubleshooting.
+
+
+
+Example:
+
+- Review logs settings during onboarding or troubleshooting.
+
+### Statistics
+
+Aggregated usage and traffic metrics.
+
+
+
+Example:
+
+- Review statistics settings during onboarding or troubleshooting.
+
+### Activity Log
+
+User actions and important events.
+
+
+
+Example:
+
+- Review activity log settings during onboarding or troubleshooting.
diff --git a/doccs/site/src/content/docs/user/mailing-lists.md b/doccs/site/src/content/docs/user/mailing-lists.md
new file mode 100644
index 0000000..0817756
--- /dev/null
+++ b/doccs/site/src/content/docs/user/mailing-lists.md
@@ -0,0 +1,21 @@
+---
+title: Mailing Lists
+description: Mailing Lists page details, screenshots, and usage examples.
+---
+
+This page provides mailing lists features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides mailing lists features for the jabali panel.
+- Use mailing lists to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use mailing lists to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/user/password-reset-request.md b/doccs/site/src/content/docs/user/password-reset-request.md
new file mode 100644
index 0000000..95888e7
--- /dev/null
+++ b/doccs/site/src/content/docs/user/password-reset-request.md
@@ -0,0 +1,21 @@
+---
+title: Password Reset Request
+description: Password Reset Request page details, screenshots, and usage examples.
+---
+
+This page provides password reset request features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides password reset request features for the jabali panel.
+- Use password reset request to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use password reset request to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/user/password-reset-reset.md b/doccs/site/src/content/docs/user/password-reset-reset.md
new file mode 100644
index 0000000..92c49a9
--- /dev/null
+++ b/doccs/site/src/content/docs/user/password-reset-reset.md
@@ -0,0 +1,21 @@
+---
+title: Password Reset
+description: Password Reset page details, screenshots, and usage examples.
+---
+
+This page provides password reset features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides password reset features for the jabali panel.
+- Use password reset to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use password reset to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/user/php-settings.md b/doccs/site/src/content/docs/user/php-settings.md
new file mode 100644
index 0000000..e085cf1
--- /dev/null
+++ b/doccs/site/src/content/docs/user/php-settings.md
@@ -0,0 +1,21 @@
+---
+title: Php Settings
+description: Php Settings page details, screenshots, and usage examples.
+---
+
+This page provides php settings features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides php settings features for the jabali panel.
+- Use php settings to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use php settings to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/user/postgresql.md b/doccs/site/src/content/docs/user/postgresql.md
new file mode 100644
index 0000000..863e4fe
--- /dev/null
+++ b/doccs/site/src/content/docs/user/postgresql.md
@@ -0,0 +1,45 @@
+---
+title: Postgresql
+description: Postgresql page details, screenshots, and usage examples.
+---
+
+This page provides postgresql features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides postgresql features for the jabali panel.
+- Use postgresql to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use postgresql to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
+
+## Tabs
+
+This page contains tabs. Each tab is captured and explained below.
+
+### Databases
+
+Imported database list from cPanel.
+
+
+
+Example:
+
+- Review databases settings during onboarding or troubleshooting.
+
+### Users
+
+Database user accounts and privileges.
+
+
+
+Example:
+
+- Review users settings during onboarding or troubleshooting.
diff --git a/doccs/site/src/content/docs/user/profile.md b/doccs/site/src/content/docs/user/profile.md
new file mode 100644
index 0000000..30f3f99
--- /dev/null
+++ b/doccs/site/src/content/docs/user/profile.md
@@ -0,0 +1,21 @@
+---
+title: Profile
+description: Profile page details, screenshots, and usage examples.
+---
+
+This page provides profile features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides profile features for the jabali panel.
+- Use profile to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use profile to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/user/protected-directories.md b/doccs/site/src/content/docs/user/protected-directories.md
new file mode 100644
index 0000000..735e94b
--- /dev/null
+++ b/doccs/site/src/content/docs/user/protected-directories.md
@@ -0,0 +1,21 @@
+---
+title: Protected Directories
+description: Protected Directories page details, screenshots, and usage examples.
+---
+
+This page provides protected directories features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides protected directories features for the jabali panel.
+- Use protected directories to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use protected directories to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/user/ssh-keys.md b/doccs/site/src/content/docs/user/ssh-keys.md
new file mode 100644
index 0000000..c044d45
--- /dev/null
+++ b/doccs/site/src/content/docs/user/ssh-keys.md
@@ -0,0 +1,21 @@
+---
+title: Ssh & Sftp
+description: Ssh & Sftp page details, screenshots, and usage examples.
+---
+
+This page provides ssh & sftp features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides ssh & sftp features for the jabali panel.
+- Use ssh & sftp to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use ssh & sftp to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/user/ssl.md b/doccs/site/src/content/docs/user/ssl.md
new file mode 100644
index 0000000..436a34f
--- /dev/null
+++ b/doccs/site/src/content/docs/user/ssl.md
@@ -0,0 +1,21 @@
+---
+title: Ssl Certificates
+description: Ssl Certificates page details, screenshots, and usage examples.
+---
+
+This page provides ssl certificates features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides ssl certificates features for the jabali panel.
+- Use ssl certificates to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use ssl certificates to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/user/two-factor-challenge.md b/doccs/site/src/content/docs/user/two-factor-challenge.md
new file mode 100644
index 0000000..bd6c19b
--- /dev/null
+++ b/doccs/site/src/content/docs/user/two-factor-challenge.md
@@ -0,0 +1,21 @@
+---
+title: Two-Factor Challenge
+description: Two-Factor Challenge page details, screenshots, and usage examples.
+---
+
+This page provides two-factor challenge features for the jabali panel.
+
+## Screenshot
+
+
+
+## What this page does
+
+- This page provides two-factor challenge features for the jabali panel.
+- Use two-factor challenge to complete common operational tasks.
+- Review this page after configuration changes to confirm results.
+
+## Typical examples
+
+- Example 1: Use two-factor challenge to complete common operational tasks.
+- Example 2: Review this page after configuration changes to confirm results.
diff --git a/doccs/site/src/content/docs/user/wordpress.md b/doccs/site/src/content/docs/user/wordpress.md
new file mode 100644
index 0000000..b0d177d
--- /dev/null
+++ b/doccs/site/src/content/docs/user/wordpress.md
@@ -0,0 +1,21 @@
+---
+title: Wordpress
+description: Wordpress page details, screenshots, and usage examples.
+---
+
+WordPress tools for installs, updates, and security actions.
+
+## Screenshot
+
+
+
+## What this page does
+
+- WordPress tools for installs, updates, and security actions.
+- Install WordPress for a new site in one click.
+- Run a security scan after updates.
+
+## Typical examples
+
+- Example 1: Install WordPress for a new site in one click.
+- Example 2: Run a security scan after updates.
diff --git a/doccs/site/tsconfig.json b/doccs/site/tsconfig.json
new file mode 100644
index 0000000..8bf91d3
--- /dev/null
+++ b/doccs/site/tsconfig.json
@@ -0,0 +1,5 @@
+{
+ "extends": "astro/tsconfigs/strict",
+ "include": [".astro/types.d.ts", "**/*"],
+ "exclude": ["dist"]
+}
diff --git a/docs/architecture/control-panel-blueprint.md b/docs/architecture/control-panel-blueprint.md
index f2f864d..2aa6d60 100644
--- a/docs/architecture/control-panel-blueprint.md
+++ b/docs/architecture/control-panel-blueprint.md
@@ -126,3 +126,8 @@ This blueprint describes a modern web hosting control panel (cPanel/DirectAdmin-
- Read-only middleware should block data mutations but allow authentication.
- Demo deployments may run without privileged agent sockets; provide static demo data for agent-dependent pages.
- Reverse proxy must be trusted to ensure Livewire update URLs are HTTPS.
+## Documentation Coverage Notes
+
+- Documentation screenshots are generated for every admin and user page, including tabs where available.
+- cPanel Migration tabs (Domains, Databases, Mailboxes, Forwarders, SSL) appear only after a backup is analyzed. Without a sample backup, those tab screenshots cannot be captured.
+- To complete coverage, provide a cPanel backup archive and run the screenshot capture flow after analysis.
diff --git a/docs/screenshots/admin-backups.png b/docs/screenshots/admin-backups.png
index 3b7f3d4..3c7d5b6 100644
Binary files a/docs/screenshots/admin-backups.png and b/docs/screenshots/admin-backups.png differ
diff --git a/docs/screenshots/admin-dashboard.png b/docs/screenshots/admin-dashboard.png
index 1adbf5a..d878802 100644
Binary files a/docs/screenshots/admin-dashboard.png and b/docs/screenshots/admin-dashboard.png differ
diff --git a/docs/screenshots/admin-dns-zones.png b/docs/screenshots/admin-dns-zones.png
index 925de19..aeae42e 100644
Binary files a/docs/screenshots/admin-dns-zones.png and b/docs/screenshots/admin-dns-zones.png differ
diff --git a/docs/screenshots/admin-security.png b/docs/screenshots/admin-security.png
index a46bea9..ff75312 100644
Binary files a/docs/screenshots/admin-security.png and b/docs/screenshots/admin-security.png differ
diff --git a/docs/screenshots/admin-server-settings.png b/docs/screenshots/admin-server-settings.png
index eab7433..16c1b4f 100644
Binary files a/docs/screenshots/admin-server-settings.png and b/docs/screenshots/admin-server-settings.png differ
diff --git a/docs/screenshots/admin-server-status.png b/docs/screenshots/admin-server-status.png
index a4e2c3a..a850028 100644
Binary files a/docs/screenshots/admin-server-status.png and b/docs/screenshots/admin-server-status.png differ
diff --git a/docs/screenshots/admin-services.png b/docs/screenshots/admin-services.png
index 2ed2459..0abfc1e 100644
Binary files a/docs/screenshots/admin-services.png and b/docs/screenshots/admin-services.png differ
diff --git a/docs/screenshots/admin-ssl-manager.png b/docs/screenshots/admin-ssl-manager.png
index 789a9e7..15a8a21 100644
Binary files a/docs/screenshots/admin-ssl-manager.png and b/docs/screenshots/admin-ssl-manager.png differ
diff --git a/docs/screenshots/admin-users.png b/docs/screenshots/admin-users.png
index e4710a7..58fc74b 100644
Binary files a/docs/screenshots/admin-users.png and b/docs/screenshots/admin-users.png differ
diff --git a/docs/screenshots/full/admin-automation-api.png b/docs/screenshots/full/admin-automation-api.png
new file mode 100644
index 0000000..029e4a4
Binary files /dev/null and b/docs/screenshots/full/admin-automation-api.png differ
diff --git a/docs/screenshots/full/admin-backup-download.png b/docs/screenshots/full/admin-backup-download.png
new file mode 100644
index 0000000..d3c2d62
Binary files /dev/null and b/docs/screenshots/full/admin-backup-download.png differ
diff --git a/docs/screenshots/full/admin-backups--tab-backups.png b/docs/screenshots/full/admin-backups--tab-backups.png
new file mode 100644
index 0000000..4d889a1
Binary files /dev/null and b/docs/screenshots/full/admin-backups--tab-backups.png differ
diff --git a/docs/screenshots/full/admin-backups--tab-destinations.png b/docs/screenshots/full/admin-backups--tab-destinations.png
new file mode 100644
index 0000000..3250684
Binary files /dev/null and b/docs/screenshots/full/admin-backups--tab-destinations.png differ
diff --git a/docs/screenshots/full/admin-backups--tab-schedules.png b/docs/screenshots/full/admin-backups--tab-schedules.png
new file mode 100644
index 0000000..91e70ab
Binary files /dev/null and b/docs/screenshots/full/admin-backups--tab-schedules.png differ
diff --git a/docs/screenshots/full/admin-backups.png b/docs/screenshots/full/admin-backups.png
new file mode 100644
index 0000000..3250684
Binary files /dev/null and b/docs/screenshots/full/admin-backups.png differ
diff --git a/docs/screenshots/full/admin-cpanel-migration.png b/docs/screenshots/full/admin-cpanel-migration.png
new file mode 100644
index 0000000..431679f
Binary files /dev/null and b/docs/screenshots/full/admin-cpanel-migration.png differ
diff --git a/docs/screenshots/full/admin-dashboard.png b/docs/screenshots/full/admin-dashboard.png
new file mode 100644
index 0000000..2c913fc
Binary files /dev/null and b/docs/screenshots/full/admin-dashboard.png differ
diff --git a/docs/screenshots/full/admin-database-tuning.png b/docs/screenshots/full/admin-database-tuning.png
new file mode 100644
index 0000000..63c95fc
Binary files /dev/null and b/docs/screenshots/full/admin-database-tuning.png differ
diff --git a/docs/screenshots/full/admin-dns-zones.png b/docs/screenshots/full/admin-dns-zones.png
new file mode 100644
index 0000000..955e643
Binary files /dev/null and b/docs/screenshots/full/admin-dns-zones.png differ
diff --git a/docs/screenshots/full/admin-email-logs.png b/docs/screenshots/full/admin-email-logs.png
new file mode 100644
index 0000000..38b095c
Binary files /dev/null and b/docs/screenshots/full/admin-email-logs.png differ
diff --git a/docs/screenshots/full/admin-email-queue.png b/docs/screenshots/full/admin-email-queue.png
new file mode 100644
index 0000000..38b095c
Binary files /dev/null and b/docs/screenshots/full/admin-email-queue.png differ
diff --git a/docs/screenshots/full/admin-geo-block-rules-create.png b/docs/screenshots/full/admin-geo-block-rules-create.png
new file mode 100644
index 0000000..dc7f9ed
Binary files /dev/null and b/docs/screenshots/full/admin-geo-block-rules-create.png differ
diff --git a/docs/screenshots/full/admin-geo-block-rules-edit.png b/docs/screenshots/full/admin-geo-block-rules-edit.png
new file mode 100644
index 0000000..c2a17c2
Binary files /dev/null and b/docs/screenshots/full/admin-geo-block-rules-edit.png differ
diff --git a/docs/screenshots/full/admin-geo-block-rules.png b/docs/screenshots/full/admin-geo-block-rules.png
new file mode 100644
index 0000000..8d532af
Binary files /dev/null and b/docs/screenshots/full/admin-geo-block-rules.png differ
diff --git a/docs/screenshots/full/admin-home.png b/docs/screenshots/full/admin-home.png
new file mode 100644
index 0000000..2c913fc
Binary files /dev/null and b/docs/screenshots/full/admin-home.png differ
diff --git a/docs/screenshots/full/admin-hosting-packages-create.png b/docs/screenshots/full/admin-hosting-packages-create.png
new file mode 100644
index 0000000..03ac40a
Binary files /dev/null and b/docs/screenshots/full/admin-hosting-packages-create.png differ
diff --git a/docs/screenshots/full/admin-hosting-packages-edit.png b/docs/screenshots/full/admin-hosting-packages-edit.png
new file mode 100644
index 0000000..0476fa2
Binary files /dev/null and b/docs/screenshots/full/admin-hosting-packages-edit.png differ
diff --git a/docs/screenshots/full/admin-hosting-packages.png b/docs/screenshots/full/admin-hosting-packages.png
new file mode 100644
index 0000000..87a6a67
Binary files /dev/null and b/docs/screenshots/full/admin-hosting-packages.png differ
diff --git a/docs/screenshots/full/admin-ip-addresses.png b/docs/screenshots/full/admin-ip-addresses.png
new file mode 100644
index 0000000..b38642c
Binary files /dev/null and b/docs/screenshots/full/admin-ip-addresses.png differ
diff --git a/docs/screenshots/full/admin-login.png b/docs/screenshots/full/admin-login.png
new file mode 100644
index 0000000..cc31f1f
Binary files /dev/null and b/docs/screenshots/full/admin-login.png differ
diff --git a/docs/screenshots/full/admin-migration--tab-cpanel-migration.png b/docs/screenshots/full/admin-migration--tab-cpanel-migration.png
new file mode 100644
index 0000000..1693a74
Binary files /dev/null and b/docs/screenshots/full/admin-migration--tab-cpanel-migration.png differ
diff --git a/docs/screenshots/full/admin-migration--tab-whm-migration.png b/docs/screenshots/full/admin-migration--tab-whm-migration.png
new file mode 100644
index 0000000..536b96e
Binary files /dev/null and b/docs/screenshots/full/admin-migration--tab-whm-migration.png differ
diff --git a/docs/screenshots/full/admin-migration.png b/docs/screenshots/full/admin-migration.png
new file mode 100644
index 0000000..1693a74
Binary files /dev/null and b/docs/screenshots/full/admin-migration.png differ
diff --git a/docs/screenshots/full/admin-password-reset-request.png b/docs/screenshots/full/admin-password-reset-request.png
new file mode 100644
index 0000000..ec6075d
Binary files /dev/null and b/docs/screenshots/full/admin-password-reset-request.png differ
diff --git a/docs/screenshots/full/admin-password-reset-reset.png b/docs/screenshots/full/admin-password-reset-reset.png
new file mode 100644
index 0000000..4f44da7
Binary files /dev/null and b/docs/screenshots/full/admin-password-reset-reset.png differ
diff --git a/docs/screenshots/full/admin-php-manager.png b/docs/screenshots/full/admin-php-manager.png
new file mode 100644
index 0000000..234a681
Binary files /dev/null and b/docs/screenshots/full/admin-php-manager.png differ
diff --git a/docs/screenshots/full/admin-security--tab-antivirus.png b/docs/screenshots/full/admin-security--tab-antivirus.png
new file mode 100644
index 0000000..012372a
Binary files /dev/null and b/docs/screenshots/full/admin-security--tab-antivirus.png differ
diff --git a/docs/screenshots/full/admin-security--tab-fail2ban.png b/docs/screenshots/full/admin-security--tab-fail2ban.png
new file mode 100644
index 0000000..012372a
Binary files /dev/null and b/docs/screenshots/full/admin-security--tab-fail2ban.png differ
diff --git a/docs/screenshots/full/admin-security--tab-firewall.png b/docs/screenshots/full/admin-security--tab-firewall.png
new file mode 100644
index 0000000..35c33fc
Binary files /dev/null and b/docs/screenshots/full/admin-security--tab-firewall.png differ
diff --git a/docs/screenshots/full/admin-security--tab-modsecurity-waf.png b/docs/screenshots/full/admin-security--tab-modsecurity-waf.png
new file mode 100644
index 0000000..b414d82
Binary files /dev/null and b/docs/screenshots/full/admin-security--tab-modsecurity-waf.png differ
diff --git a/docs/screenshots/full/admin-security--tab-overview.png b/docs/screenshots/full/admin-security--tab-overview.png
new file mode 100644
index 0000000..1611179
Binary files /dev/null and b/docs/screenshots/full/admin-security--tab-overview.png differ
diff --git a/docs/screenshots/full/admin-security--tab-ssh.png b/docs/screenshots/full/admin-security--tab-ssh.png
new file mode 100644
index 0000000..012372a
Binary files /dev/null and b/docs/screenshots/full/admin-security--tab-ssh.png differ
diff --git a/docs/screenshots/full/admin-security--tab-vulnerability-scanner.png b/docs/screenshots/full/admin-security--tab-vulnerability-scanner.png
new file mode 100644
index 0000000..e7aa16d
Binary files /dev/null and b/docs/screenshots/full/admin-security--tab-vulnerability-scanner.png differ
diff --git a/docs/screenshots/full/admin-security.png b/docs/screenshots/full/admin-security.png
new file mode 100644
index 0000000..1611179
Binary files /dev/null and b/docs/screenshots/full/admin-security.png differ
diff --git a/docs/screenshots/full/admin-server-settings--tab-database-tuning.png b/docs/screenshots/full/admin-server-settings--tab-database-tuning.png
new file mode 100644
index 0000000..1b25340
Binary files /dev/null and b/docs/screenshots/full/admin-server-settings--tab-database-tuning.png differ
diff --git a/docs/screenshots/full/admin-server-settings--tab-dns.png b/docs/screenshots/full/admin-server-settings--tab-dns.png
new file mode 100644
index 0000000..90cd53f
Binary files /dev/null and b/docs/screenshots/full/admin-server-settings--tab-dns.png differ
diff --git a/docs/screenshots/full/admin-server-settings--tab-email.png b/docs/screenshots/full/admin-server-settings--tab-email.png
new file mode 100644
index 0000000..31de073
Binary files /dev/null and b/docs/screenshots/full/admin-server-settings--tab-email.png differ
diff --git a/docs/screenshots/full/admin-server-settings--tab-general.png b/docs/screenshots/full/admin-server-settings--tab-general.png
new file mode 100644
index 0000000..a745c29
Binary files /dev/null and b/docs/screenshots/full/admin-server-settings--tab-general.png differ
diff --git a/docs/screenshots/full/admin-server-settings--tab-notifications.png b/docs/screenshots/full/admin-server-settings--tab-notifications.png
new file mode 100644
index 0000000..1c925de
Binary files /dev/null and b/docs/screenshots/full/admin-server-settings--tab-notifications.png differ
diff --git a/docs/screenshots/full/admin-server-settings--tab-php-fpm.png b/docs/screenshots/full/admin-server-settings--tab-php-fpm.png
new file mode 100644
index 0000000..65ea45f
Binary files /dev/null and b/docs/screenshots/full/admin-server-settings--tab-php-fpm.png differ
diff --git a/docs/screenshots/full/admin-server-settings--tab-storage.png b/docs/screenshots/full/admin-server-settings--tab-storage.png
new file mode 100644
index 0000000..9ed0ba4
Binary files /dev/null and b/docs/screenshots/full/admin-server-settings--tab-storage.png differ
diff --git a/docs/screenshots/full/admin-server-settings.png b/docs/screenshots/full/admin-server-settings.png
new file mode 100644
index 0000000..a745c29
Binary files /dev/null and b/docs/screenshots/full/admin-server-settings.png differ
diff --git a/docs/screenshots/full/admin-server-status.png b/docs/screenshots/full/admin-server-status.png
new file mode 100644
index 0000000..2204a5d
Binary files /dev/null and b/docs/screenshots/full/admin-server-status.png differ
diff --git a/docs/screenshots/full/admin-server-updates.png b/docs/screenshots/full/admin-server-updates.png
new file mode 100644
index 0000000..5a2172d
Binary files /dev/null and b/docs/screenshots/full/admin-server-updates.png differ
diff --git a/docs/screenshots/full/admin-services.png b/docs/screenshots/full/admin-services.png
new file mode 100644
index 0000000..1ccec0f
Binary files /dev/null and b/docs/screenshots/full/admin-services.png differ
diff --git a/docs/screenshots/full/admin-ssl-manager.png b/docs/screenshots/full/admin-ssl-manager.png
new file mode 100644
index 0000000..e75e384
Binary files /dev/null and b/docs/screenshots/full/admin-ssl-manager.png differ
diff --git a/docs/screenshots/full/admin-two-factor-challenge.png b/docs/screenshots/full/admin-two-factor-challenge.png
new file mode 100644
index 0000000..4231887
Binary files /dev/null and b/docs/screenshots/full/admin-two-factor-challenge.png differ
diff --git a/docs/screenshots/full/admin-users-create.png b/docs/screenshots/full/admin-users-create.png
new file mode 100644
index 0000000..3e5e9d5
Binary files /dev/null and b/docs/screenshots/full/admin-users-create.png differ
diff --git a/docs/screenshots/full/admin-users-edit.png b/docs/screenshots/full/admin-users-edit.png
new file mode 100644
index 0000000..f8ed56e
Binary files /dev/null and b/docs/screenshots/full/admin-users-edit.png differ
diff --git a/docs/screenshots/full/admin-users.png b/docs/screenshots/full/admin-users.png
new file mode 100644
index 0000000..c011d59
Binary files /dev/null and b/docs/screenshots/full/admin-users.png differ
diff --git a/docs/screenshots/full/admin-waf.png b/docs/screenshots/full/admin-waf.png
new file mode 100644
index 0000000..ebc5268
Binary files /dev/null and b/docs/screenshots/full/admin-waf.png differ
diff --git a/docs/screenshots/full/admin-webhook-endpoints-create.png b/docs/screenshots/full/admin-webhook-endpoints-create.png
new file mode 100644
index 0000000..b5fe648
Binary files /dev/null and b/docs/screenshots/full/admin-webhook-endpoints-create.png differ
diff --git a/docs/screenshots/full/admin-webhook-endpoints-edit.png b/docs/screenshots/full/admin-webhook-endpoints-edit.png
new file mode 100644
index 0000000..7764fa3
Binary files /dev/null and b/docs/screenshots/full/admin-webhook-endpoints-edit.png differ
diff --git a/docs/screenshots/full/admin-webhook-endpoints.png b/docs/screenshots/full/admin-webhook-endpoints.png
new file mode 100644
index 0000000..4537eb4
Binary files /dev/null and b/docs/screenshots/full/admin-webhook-endpoints.png differ
diff --git a/docs/screenshots/full/admin-whm-migration.png b/docs/screenshots/full/admin-whm-migration.png
new file mode 100644
index 0000000..e47a01c
Binary files /dev/null and b/docs/screenshots/full/admin-whm-migration.png differ
diff --git a/docs/screenshots/full/user-backup-download.png b/docs/screenshots/full/user-backup-download.png
new file mode 100644
index 0000000..e37d205
Binary files /dev/null and b/docs/screenshots/full/user-backup-download.png differ
diff --git a/docs/screenshots/full/user-backups--tab-my-backups.png b/docs/screenshots/full/user-backups--tab-my-backups.png
new file mode 100644
index 0000000..622d004
Binary files /dev/null and b/docs/screenshots/full/user-backups--tab-my-backups.png differ
diff --git a/docs/screenshots/full/user-backups--tab-restore-history.png b/docs/screenshots/full/user-backups--tab-restore-history.png
new file mode 100644
index 0000000..e61935b
Binary files /dev/null and b/docs/screenshots/full/user-backups--tab-restore-history.png differ
diff --git a/docs/screenshots/full/user-backups--tab-server-backups.png b/docs/screenshots/full/user-backups--tab-server-backups.png
new file mode 100644
index 0000000..26d6b5b
Binary files /dev/null and b/docs/screenshots/full/user-backups--tab-server-backups.png differ
diff --git a/docs/screenshots/full/user-backups--tab-sftp-destinations.png b/docs/screenshots/full/user-backups--tab-sftp-destinations.png
new file mode 100644
index 0000000..6dda5e7
Binary files /dev/null and b/docs/screenshots/full/user-backups--tab-sftp-destinations.png differ
diff --git a/docs/screenshots/full/user-backups.png b/docs/screenshots/full/user-backups.png
new file mode 100644
index 0000000..622d004
Binary files /dev/null and b/docs/screenshots/full/user-backups.png differ
diff --git a/docs/screenshots/full/user-cdn-integration.png b/docs/screenshots/full/user-cdn-integration.png
new file mode 100644
index 0000000..19ca539
Binary files /dev/null and b/docs/screenshots/full/user-cdn-integration.png differ
diff --git a/docs/screenshots/full/user-cpanel-migration.png b/docs/screenshots/full/user-cpanel-migration.png
new file mode 100644
index 0000000..76c81a2
Binary files /dev/null and b/docs/screenshots/full/user-cpanel-migration.png differ
diff --git a/docs/screenshots/full/user-cron-jobs.png b/docs/screenshots/full/user-cron-jobs.png
new file mode 100644
index 0000000..6711257
Binary files /dev/null and b/docs/screenshots/full/user-cron-jobs.png differ
diff --git a/docs/screenshots/full/user-databases.png b/docs/screenshots/full/user-databases.png
new file mode 100644
index 0000000..a9b5f24
Binary files /dev/null and b/docs/screenshots/full/user-databases.png differ
diff --git a/docs/screenshots/full/user-dns-records.png b/docs/screenshots/full/user-dns-records.png
new file mode 100644
index 0000000..467a63c
Binary files /dev/null and b/docs/screenshots/full/user-dns-records.png differ
diff --git a/docs/screenshots/full/user-domains.png b/docs/screenshots/full/user-domains.png
new file mode 100644
index 0000000..f8193a4
Binary files /dev/null and b/docs/screenshots/full/user-domains.png differ
diff --git a/docs/screenshots/full/user-email--tab-autoresponders.png b/docs/screenshots/full/user-email--tab-autoresponders.png
new file mode 100644
index 0000000..87b8565
Binary files /dev/null and b/docs/screenshots/full/user-email--tab-autoresponders.png differ
diff --git a/docs/screenshots/full/user-email--tab-catch-all.png b/docs/screenshots/full/user-email--tab-catch-all.png
new file mode 100644
index 0000000..206c277
Binary files /dev/null and b/docs/screenshots/full/user-email--tab-catch-all.png differ
diff --git a/docs/screenshots/full/user-email--tab-forwarders.png b/docs/screenshots/full/user-email--tab-forwarders.png
new file mode 100644
index 0000000..4041c7a
Binary files /dev/null and b/docs/screenshots/full/user-email--tab-forwarders.png differ
diff --git a/docs/screenshots/full/user-email--tab-logs.png b/docs/screenshots/full/user-email--tab-logs.png
new file mode 100644
index 0000000..2af2b03
Binary files /dev/null and b/docs/screenshots/full/user-email--tab-logs.png differ
diff --git a/docs/screenshots/full/user-email--tab-mailboxes.png b/docs/screenshots/full/user-email--tab-mailboxes.png
new file mode 100644
index 0000000..dec06fa
Binary files /dev/null and b/docs/screenshots/full/user-email--tab-mailboxes.png differ
diff --git a/docs/screenshots/full/user-email--tab-spam-settings.png b/docs/screenshots/full/user-email--tab-spam-settings.png
new file mode 100644
index 0000000..388ac6f
Binary files /dev/null and b/docs/screenshots/full/user-email--tab-spam-settings.png differ
diff --git a/docs/screenshots/full/user-email.png b/docs/screenshots/full/user-email.png
new file mode 100644
index 0000000..dec06fa
Binary files /dev/null and b/docs/screenshots/full/user-email.png differ
diff --git a/docs/screenshots/full/user-files.png b/docs/screenshots/full/user-files.png
new file mode 100644
index 0000000..dd27c60
Binary files /dev/null and b/docs/screenshots/full/user-files.png differ
diff --git a/docs/screenshots/full/user-git-deployment.png b/docs/screenshots/full/user-git-deployment.png
new file mode 100644
index 0000000..30e80a5
Binary files /dev/null and b/docs/screenshots/full/user-git-deployment.png differ
diff --git a/docs/screenshots/full/user-home.png b/docs/screenshots/full/user-home.png
new file mode 100644
index 0000000..3a6a106
Binary files /dev/null and b/docs/screenshots/full/user-home.png differ
diff --git a/docs/screenshots/full/user-image-optimization.png b/docs/screenshots/full/user-image-optimization.png
new file mode 100644
index 0000000..41274ea
Binary files /dev/null and b/docs/screenshots/full/user-image-optimization.png differ
diff --git a/docs/screenshots/full/user-login.png b/docs/screenshots/full/user-login.png
new file mode 100644
index 0000000..4d10057
Binary files /dev/null and b/docs/screenshots/full/user-login.png differ
diff --git a/docs/screenshots/full/user-logs--tab-activity-log.png b/docs/screenshots/full/user-logs--tab-activity-log.png
new file mode 100644
index 0000000..ef5ef0f
Binary files /dev/null and b/docs/screenshots/full/user-logs--tab-activity-log.png differ
diff --git a/docs/screenshots/full/user-logs--tab-logs.png b/docs/screenshots/full/user-logs--tab-logs.png
new file mode 100644
index 0000000..5a58df0
Binary files /dev/null and b/docs/screenshots/full/user-logs--tab-logs.png differ
diff --git a/docs/screenshots/full/user-logs--tab-statistics.png b/docs/screenshots/full/user-logs--tab-statistics.png
new file mode 100644
index 0000000..a66cd0e
Binary files /dev/null and b/docs/screenshots/full/user-logs--tab-statistics.png differ
diff --git a/docs/screenshots/full/user-logs.png b/docs/screenshots/full/user-logs.png
new file mode 100644
index 0000000..5a58df0
Binary files /dev/null and b/docs/screenshots/full/user-logs.png differ
diff --git a/docs/screenshots/full/user-mailing-lists.png b/docs/screenshots/full/user-mailing-lists.png
new file mode 100644
index 0000000..7fd4532
Binary files /dev/null and b/docs/screenshots/full/user-mailing-lists.png differ
diff --git a/docs/screenshots/full/user-password-reset-request.png b/docs/screenshots/full/user-password-reset-request.png
new file mode 100644
index 0000000..749a30f
Binary files /dev/null and b/docs/screenshots/full/user-password-reset-request.png differ
diff --git a/docs/screenshots/full/user-password-reset-reset.png b/docs/screenshots/full/user-password-reset-reset.png
new file mode 100644
index 0000000..4f44da7
Binary files /dev/null and b/docs/screenshots/full/user-password-reset-reset.png differ
diff --git a/docs/screenshots/full/user-php-settings.png b/docs/screenshots/full/user-php-settings.png
new file mode 100644
index 0000000..1b598ce
Binary files /dev/null and b/docs/screenshots/full/user-php-settings.png differ
diff --git a/docs/screenshots/full/user-postgresql--tab-databases.png b/docs/screenshots/full/user-postgresql--tab-databases.png
new file mode 100644
index 0000000..2b693cb
Binary files /dev/null and b/docs/screenshots/full/user-postgresql--tab-databases.png differ
diff --git a/docs/screenshots/full/user-postgresql--tab-users.png b/docs/screenshots/full/user-postgresql--tab-users.png
new file mode 100644
index 0000000..b2626e0
Binary files /dev/null and b/docs/screenshots/full/user-postgresql--tab-users.png differ
diff --git a/docs/screenshots/full/user-postgresql.png b/docs/screenshots/full/user-postgresql.png
new file mode 100644
index 0000000..2b693cb
Binary files /dev/null and b/docs/screenshots/full/user-postgresql.png differ
diff --git a/docs/screenshots/full/user-profile.png b/docs/screenshots/full/user-profile.png
new file mode 100644
index 0000000..7a9113a
Binary files /dev/null and b/docs/screenshots/full/user-profile.png differ
diff --git a/docs/screenshots/full/user-protected-directories.png b/docs/screenshots/full/user-protected-directories.png
new file mode 100644
index 0000000..6c15adf
Binary files /dev/null and b/docs/screenshots/full/user-protected-directories.png differ
diff --git a/docs/screenshots/full/user-ssh-keys.png b/docs/screenshots/full/user-ssh-keys.png
new file mode 100644
index 0000000..0f4c67f
Binary files /dev/null and b/docs/screenshots/full/user-ssh-keys.png differ
diff --git a/docs/screenshots/full/user-ssl.png b/docs/screenshots/full/user-ssl.png
new file mode 100644
index 0000000..7f45a91
Binary files /dev/null and b/docs/screenshots/full/user-ssl.png differ
diff --git a/docs/screenshots/full/user-two-factor-challenge.png b/docs/screenshots/full/user-two-factor-challenge.png
new file mode 100644
index 0000000..15481ec
Binary files /dev/null and b/docs/screenshots/full/user-two-factor-challenge.png differ
diff --git a/docs/screenshots/full/user-wordpress.png b/docs/screenshots/full/user-wordpress.png
new file mode 100644
index 0000000..dcc8b2f
Binary files /dev/null and b/docs/screenshots/full/user-wordpress.png differ
diff --git a/docs/screenshots/user-backups.png b/docs/screenshots/user-backups.png
index 14e3e7a..7cd42fd 100644
Binary files a/docs/screenshots/user-backups.png and b/docs/screenshots/user-backups.png differ
diff --git a/docs/screenshots/user-cpanel-migration.png b/docs/screenshots/user-cpanel-migration.png
index e19ef01..121e074 100644
Binary files a/docs/screenshots/user-cpanel-migration.png and b/docs/screenshots/user-cpanel-migration.png differ
diff --git a/docs/screenshots/user-dashboard.png b/docs/screenshots/user-dashboard.png
index f223261..f9b2a38 100644
Binary files a/docs/screenshots/user-dashboard.png and b/docs/screenshots/user-dashboard.png differ
diff --git a/docs/screenshots/user-domains.png b/docs/screenshots/user-domains.png
index e040c55..aaff6ba 100644
Binary files a/docs/screenshots/user-domains.png and b/docs/screenshots/user-domains.png differ
diff --git a/install.sh b/install.sh
index be0b43d..613b3eb 100755
--- a/install.sh
+++ b/install.sh
@@ -16,7 +16,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [[ -f "$SCRIPT_DIR/VERSION" ]]; then
JABALI_VERSION="$(sed -n 's/^VERSION=//p' "$SCRIPT_DIR/VERSION")"
fi
-JABALI_VERSION="${JABALI_VERSION:-0.9-rc53}"
+JABALI_VERSION="${JABALI_VERSION:-0.9-rc54}"
# Colors
RED='\033[0;31m'
diff --git a/resources/views/filament/jabali/pages/files.blade.php b/resources/views/filament/jabali/pages/files.blade.php
index e54577c..3c23b0f 100644
--- a/resources/views/filament/jabali/pages/files.blade.php
+++ b/resources/views/filament/jabali/pages/files.blade.php
@@ -12,6 +12,7 @@
{{ __('and') }}
+ {{ __('and') }}
{{ __('folders unless you know what you are doing.') }}
diff --git a/tests/docs-pages.json b/tests/docs-pages.json
new file mode 100644
index 0000000..31797b6
--- /dev/null
+++ b/tests/docs-pages.json
@@ -0,0 +1,497 @@
+[
+ {
+ "panel": "admin",
+ "uri": "jabali-admin",
+ "name": "filament.admin.home",
+ "label": "jabali-admin",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/automation-api",
+ "name": "filament.admin.pages.automation-api",
+ "label": "API Access",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/backup-download",
+ "name": "filament.admin.pages.backup-download",
+ "label": "jabali-admin/backup-download",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/backups",
+ "name": "filament.admin.pages.backups",
+ "label": "Backups",
+ "tabs": [
+ "Destinations",
+ "Schedules",
+ "Backups"
+ ]
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/cpanel-migration",
+ "name": "filament.admin.pages.cpanel-migration",
+ "label": "cPanel Migration",
+ "tabs": [
+ "Domains",
+ "Databases",
+ "Mailboxes",
+ "Forwarders",
+ "SSL"
+ ]
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/dashboard",
+ "name": "filament.admin.pages.dashboard",
+ "label": "Dashboard",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/database-tuning",
+ "name": "filament.admin.pages.database-tuning",
+ "label": "Database Tuning",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/dns-zones",
+ "name": "filament.admin.pages.dns-zones",
+ "label": "DNS Zones",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/email-logs",
+ "name": "filament.admin.pages.email-logs",
+ "label": "Email Logs",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/email-queue",
+ "name": "filament.admin.pages.email-queue",
+ "label": "Email Queue",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/geo-block-rules",
+ "name": "filament.admin.resources.geo-block-rules.index",
+ "label": "jabali-admin/geo-block-rules",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/geo-block-rules/create",
+ "name": "filament.admin.resources.geo-block-rules.create",
+ "label": "jabali-admin/geo-block-rules/create",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/geo-block-rules/{record}/edit",
+ "name": "filament.admin.resources.geo-block-rules.edit",
+ "label": "jabali-admin/geo-block-rules/{record}/edit",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/hosting-packages",
+ "name": "filament.admin.resources.hosting-packages.index",
+ "label": "jabali-admin/hosting-packages",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/hosting-packages/create",
+ "name": "filament.admin.resources.hosting-packages.create",
+ "label": "jabali-admin/hosting-packages/create",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/hosting-packages/{record}/edit",
+ "name": "filament.admin.resources.hosting-packages.edit",
+ "label": "jabali-admin/hosting-packages/{record}/edit",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/ip-addresses",
+ "name": "filament.admin.pages.ip-addresses",
+ "label": "IP Addresses",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/login",
+ "name": "filament.admin.auth.login",
+ "label": "jabali-admin/login",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/migration",
+ "name": "filament.admin.pages.migration",
+ "label": "Migration",
+ "tabs": [
+ "cPanel Migration",
+ "WHM Migration"
+ ]
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/password-reset/request",
+ "name": "filament.admin.auth.password-reset.request",
+ "label": "jabali-admin/password-reset/request",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/password-reset/reset",
+ "name": "filament.admin.auth.password-reset.reset",
+ "label": "jabali-admin/password-reset/reset",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/php-manager",
+ "name": "filament.admin.pages.php-manager",
+ "label": "PHP Manager",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/security",
+ "name": "filament.admin.pages.security",
+ "label": "Security",
+ "tabs": [
+ "Overview",
+ "Firewall",
+ "ModSecurity / WAF",
+ "Fail2ban",
+ "Antivirus",
+ "SSH",
+ "Vulnerability Scanner"
+ ]
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/server-settings",
+ "name": "filament.admin.pages.server-settings",
+ "label": "Server Settings",
+ "tabs": [
+ "General",
+ "DNS",
+ "Storage",
+ "Email",
+ "Notifications",
+ "PHP-FPM",
+ "Database Tuning"
+ ]
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/server-status",
+ "name": "filament.admin.pages.server-status",
+ "label": "Server Status",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/server-updates",
+ "name": "filament.admin.pages.server-updates",
+ "label": "System Updates",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/services",
+ "name": "filament.admin.pages.services",
+ "label": "Services",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/ssl-manager",
+ "name": "filament.admin.pages.ssl-manager",
+ "label": "SSL Manager",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/two-factor-challenge",
+ "name": "filament.admin.auth.two-factor-challenge",
+ "label": "jabali-admin/two-factor-challenge",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/users",
+ "name": "filament.admin.resources.users.index",
+ "label": "jabali-admin/users",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/users/create",
+ "name": "filament.admin.resources.users.create",
+ "label": "jabali-admin/users/create",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/users/{record}/edit",
+ "name": "filament.admin.resources.users.edit",
+ "label": "jabali-admin/users/{record}/edit",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/waf",
+ "name": "filament.admin.pages.waf",
+ "label": "ModSecurity / WAF",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/webhook-endpoints",
+ "name": "filament.admin.resources.webhook-endpoints.index",
+ "label": "jabali-admin/webhook-endpoints",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/webhook-endpoints/create",
+ "name": "filament.admin.resources.webhook-endpoints.create",
+ "label": "jabali-admin/webhook-endpoints/create",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/webhook-endpoints/{record}/edit",
+ "name": "filament.admin.resources.webhook-endpoints.edit",
+ "label": "jabali-admin/webhook-endpoints/{record}/edit",
+ "tabs": []
+ },
+ {
+ "panel": "admin",
+ "uri": "jabali-admin/whm-migration",
+ "name": "filament.admin.pages.whm-migration",
+ "label": "WHM Migration",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel",
+ "name": "filament.jabali.pages.dashboard",
+ "label": "Dashboard",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/backup-download",
+ "name": "filament.jabali.pages.backup-download",
+ "label": "jabali-panel/backup-download",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/backups",
+ "name": "filament.jabali.pages.backups",
+ "label": "Backups",
+ "tabs": [
+ "My Backups",
+ "Server Backups",
+ "SFTP Destinations",
+ "Restore History"
+ ]
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/cdn-integration",
+ "name": "filament.jabali.pages.cdn-integration",
+ "label": "CDN Integration",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/cpanel-migration",
+ "name": "filament.jabali.pages.cpanel-migration",
+ "label": "cPanel Migration",
+ "tabs": [
+ "Domains",
+ "Databases",
+ "Mailboxes",
+ "Forwarders",
+ "SSL"
+ ]
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/cron-jobs",
+ "name": "filament.jabali.pages.cron-jobs",
+ "label": "Cron Jobs",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/databases",
+ "name": "filament.jabali.pages.databases",
+ "label": "Databases",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/dns-records",
+ "name": "filament.jabali.pages.dns-records",
+ "label": "DNS Records",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/domains",
+ "name": "filament.jabali.pages.domains",
+ "label": "Domains",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/email",
+ "name": "filament.jabali.pages.email",
+ "label": "Email",
+ "tabs": [
+ "Mailboxes",
+ "Forwarders",
+ "Autoresponders",
+ "Catch-All",
+ "Logs",
+ "Spam Settings"
+ ]
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/files",
+ "name": "filament.jabali.pages.files",
+ "label": "Files",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/git-deployment",
+ "name": "filament.jabali.pages.git-deployment",
+ "label": "Git Deployment",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/image-optimization",
+ "name": "filament.jabali.pages.image-optimization",
+ "label": "Image Optimization",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/login",
+ "name": "filament.jabali.auth.login",
+ "label": "jabali-panel/login",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/logs",
+ "name": "filament.jabali.pages.logs",
+ "label": "Logs & Statistics",
+ "tabs": [
+ "Logs",
+ "Statistics",
+ "Activity Log"
+ ]
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/mailing-lists",
+ "name": "filament.jabali.pages.mailing-lists",
+ "label": "Mailing Lists",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/password-reset/request",
+ "name": "filament.jabali.auth.password-reset.request",
+ "label": "jabali-panel/password-reset/request",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/password-reset/reset",
+ "name": "filament.jabali.auth.password-reset.reset",
+ "label": "jabali-panel/password-reset/reset",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/php-settings",
+ "name": "filament.jabali.pages.php-settings",
+ "label": "PHP Settings",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/postgresql",
+ "name": "filament.jabali.pages.postgresql",
+ "label": "PostgreSQL",
+ "tabs": [
+ "Databases",
+ "Users"
+ ]
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/profile",
+ "name": "filament.jabali.auth.profile",
+ "label": "jabali-panel/profile",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/protected-directories",
+ "name": "filament.jabali.pages.protected-directories",
+ "label": "Protected Directories",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/ssh-keys",
+ "name": "filament.jabali.pages.ssh-keys",
+ "label": "SSH & SFTP",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/ssl",
+ "name": "filament.jabali.pages.ssl",
+ "label": "SSL Certificates",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/two-factor-challenge",
+ "name": "filament.jabali.auth.two-factor-challenge",
+ "label": "jabali-panel/two-factor-challenge",
+ "tabs": []
+ },
+ {
+ "panel": "jabali",
+ "uri": "jabali-panel/wordpress",
+ "name": "filament.jabali.pages.wordpress",
+ "label": "WordPress",
+ "tabs": []
+ }
+]
\ No newline at end of file
diff --git a/tests/take-docs-screenshots.cjs b/tests/take-docs-screenshots.cjs
new file mode 100644
index 0000000..3c28218
--- /dev/null
+++ b/tests/take-docs-screenshots.cjs
@@ -0,0 +1,246 @@
+#!/usr/bin/env node
+/**
+ * Generate documentation screenshots for every admin/user route and each tab.
+ */
+
+const fs = require('fs');
+const path = require('path');
+const { execSync } = require('child_process');
+const puppeteer = require('puppeteer');
+
+const args = process.argv.slice(2);
+const getArg = (key, fallback) => {
+ const arg = args.find((item) => item.startsWith(`--${key}=`));
+ return arg ? arg.split('=').slice(1).join('=') : fallback;
+};
+const hasFlag = (flag) => args.includes(`--${flag}`);
+
+const CONFIG = {
+ baseUrl: getArg('base-url', 'https://jabali.lan'),
+ outputDir: getArg('output-dir', '/var/www/jabali/docs/screenshots/full'),
+ pagesJson: getArg('pages-json', '/var/www/jabali/tests/docs-pages.json'),
+ admin: {
+ email: getArg('admin-email', 'admin@jabali.lan'),
+ password: getArg('admin-password', 'q1w2E#R$'),
+ path: getArg('admin-path', '/jabali-admin'),
+ },
+ user: {
+ path: getArg('user-path', '/jabali-panel'),
+ },
+ impersonateUserId: getArg('impersonate-user-id', '9'),
+ skipAdmin: hasFlag('skip-admin'),
+ skipUser: hasFlag('skip-user'),
+ fullPage: hasFlag('full-page'),
+ onlyMissing: hasFlag('only-missing'),
+};
+
+const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
+
+function slugify(value) {
+ return value
+ .toLowerCase()
+ .replace(/[^a-z0-9]+/g, '-')
+ .replace(/^-+|-+$/g, '');
+}
+
+function loadPages() {
+ return JSON.parse(fs.readFileSync(CONFIG.pagesJson, 'utf-8'));
+}
+
+function queryId(table) {
+ try {
+ const out = execSync(
+ `sqlite3 /var/www/jabali/database/database.sqlite "select id from ${table} limit 1;"`,
+ { encoding: 'utf-8' }
+ ).trim();
+ return out || null;
+ } catch (err) {
+ return null;
+ }
+}
+
+function applyRecordIds(uri) {
+ if (!uri.includes('{record}')) return uri;
+ const resourceMap = {
+ 'jabali-admin/users': 'users',
+ 'jabali-admin/hosting-packages': 'hosting_packages',
+ 'jabali-admin/geo-block-rules': 'geo_block_rules',
+ 'jabali-admin/webhook-endpoints': 'webhook_endpoints',
+ };
+ const base = uri.split('/{record}')[0];
+ const table = resourceMap[base];
+ if (!table) return uri;
+ const id = queryId(table);
+ if (!id) return uri;
+ return uri.replace('{record}', id);
+}
+
+async function loginPanel(page, panelName, basePath, credentials) {
+ console.log(`Logging in to ${panelName} panel...`);
+ await page.goto(`${CONFIG.baseUrl}${basePath}/login`, { waitUntil: 'networkidle0' });
+ await wait(1500);
+ await page.type('input[type="email"]', credentials.email);
+ await page.type('input[type="password"]', credentials.password);
+ await page.click('button[type="submit"]');
+ await wait(4000);
+ const currentUrl = page.url();
+ if (currentUrl.includes('/login')) {
+ throw new Error(`${panelName} login failed - still on login page`);
+ }
+ console.log(`${panelName} login successful!\n`);
+}
+
+async function loginUserViaImpersonation(page) {
+ if (!CONFIG.impersonateUserId) {
+ throw new Error('Missing --impersonate-user-id for user screenshots');
+ }
+ await loginPanel(page, 'Admin', CONFIG.admin.path, CONFIG.admin);
+ const impersonateUrl = `${CONFIG.baseUrl}/impersonate/start/${CONFIG.impersonateUserId}`;
+ console.log(`Impersonating user via: ${impersonateUrl}`);
+ await page.goto(impersonateUrl, { waitUntil: 'networkidle0' });
+ await wait(2000);
+ const currentUrl = page.url();
+ if (currentUrl.includes('/login')) {
+ throw new Error('Impersonation failed - still on login page');
+ }
+ console.log('User impersonation successful!\n');
+}
+
+async function clickTab(page, tabLabel) {
+ const normalized = tabLabel.trim().toLowerCase();
+ const clicked = await page.evaluate((label) => {
+ const tabs = Array.from(document.querySelectorAll('[role="tab"], button'));
+ const match = tabs.find((el) => {
+ const text = (el.textContent || '').trim().toLowerCase();
+ return text === label;
+ }) || tabs.find((el) => {
+ const text = (el.textContent || '').trim().toLowerCase();
+ return text.includes(label);
+ });
+ if (match) {
+ match.click();
+ return true;
+ }
+ return false;
+ }, normalized);
+ if (clicked) {
+ await wait(1500);
+ }
+ return clicked;
+}
+
+async function captureRoute(context, entry, prefix) {
+ const page = await context.newPage();
+ await page.setViewport({ width: 1400, height: 900 });
+
+ const uri = applyRecordIds(entry.uri);
+ const url = `${CONFIG.baseUrl}/${uri}`.replace(/\/+$/, '');
+ const baseName = `${prefix}-${slugify(uri.replace(prefix === 'admin' ? 'jabali-admin' : 'jabali-panel', '')) || 'home'}`;
+ const filename = `${baseName}.png`;
+ const filepath = path.join(CONFIG.outputDir, filename);
+
+ const skipBase = CONFIG.onlyMissing && fs.existsSync(filepath);
+
+ try {
+ await page.goto(url, { waitUntil: 'networkidle0', timeout: 45000 });
+ await wait(2000);
+
+ if (!skipBase) {
+ await page.screenshot({ path: filepath, fullPage: CONFIG.fullPage });
+ console.log(`Saved: ${filepath}`);
+ }
+
+ if (entry.tabs && entry.tabs.length) {
+ for (const tab of entry.tabs) {
+ const tabFile = `${baseName}--tab-${slugify(tab)}.png`;
+ const tabPath = path.join(CONFIG.outputDir, tabFile);
+ if (CONFIG.onlyMissing && fs.existsSync(tabPath)) {
+ continue;
+ }
+ const clicked = await clickTab(page, tab);
+ if (!clicked) {
+ console.log(` Tab not found: ${tab}`);
+ continue;
+ }
+ await page.screenshot({ path: tabPath, fullPage: CONFIG.fullPage });
+ console.log(` Tab saved: ${tabPath}`);
+ }
+ }
+ } catch (err) {
+ console.log(`Error capturing ${url}: ${err.message}`);
+ } finally {
+ await page.close();
+ }
+}
+
+async function captureAuthPages() {
+ const pages = loadPages();
+ const authUris = pages.filter((entry) => entry.uri.includes('login') || entry.uri.includes('password-reset') || entry.uri.includes('two-factor'));
+ if (!authUris.length) return;
+
+ const browser = await puppeteer.launch({
+ headless: 'new',
+ args: ['--no-sandbox', '--disable-setuid-sandbox', '--ignore-certificate-errors'],
+ });
+
+ const context = await browser.createBrowserContext();
+ for (const entry of authUris) {
+ const prefix = entry.panel === 'admin' ? 'admin' : 'user';
+ await captureRoute(context, entry, prefix);
+ }
+ await browser.close();
+}
+
+async function main() {
+ fs.mkdirSync(CONFIG.outputDir, { recursive: true });
+ const pages = loadPages();
+
+ await captureAuthPages();
+
+ const browser = await puppeteer.launch({
+ headless: 'new',
+ args: ['--no-sandbox', '--disable-setuid-sandbox', '--ignore-certificate-errors'],
+ });
+
+ if (!CONFIG.skipAdmin) {
+ const context = await browser.createBrowserContext();
+ const page = await context.newPage();
+ await page.setViewport({ width: 1400, height: 900 });
+ await loginPanel(page, 'Admin', CONFIG.admin.path, CONFIG.admin);
+ await page.close();
+
+ for (const entry of pages.filter((e) => e.panel === 'admin')) {
+ if (entry.uri.includes('login') || entry.uri.includes('password-reset') || entry.uri.includes('two-factor')) {
+ continue;
+ }
+ await captureRoute(context, entry, 'admin');
+ }
+
+ await context.close();
+ }
+
+ if (!CONFIG.skipUser) {
+ const context = await browser.createBrowserContext();
+ const page = await context.newPage();
+ await page.setViewport({ width: 1400, height: 900 });
+ await loginUserViaImpersonation(page);
+ await page.close();
+
+ for (const entry of pages.filter((e) => e.panel === 'jabali')) {
+ if (entry.uri.includes('login') || entry.uri.includes('password-reset') || entry.uri.includes('two-factor')) {
+ continue;
+ }
+ await captureRoute(context, entry, 'user');
+ }
+
+ await context.close();
+ }
+
+ await browser.close();
+ console.log('Documentation screenshots completed.');
+}
+
+main().catch((err) => {
+ console.error(err);
+ process.exit(1);
+});