From 13d3d4e87ec09c775e5a118174ac11d01454f326 Mon Sep 17 00:00:00 2001 From: Marco Curatitoli Date: Mon, 3 Nov 2025 11:49:05 +0100 Subject: [PATCH 01/33] use button in navigation panel --- src/Concerns/HasKnowledgeBasePanelButton.php | 2 +- src/Plugins/KnowledgeBaseCompanionPlugin.php | 24 ++++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Concerns/HasKnowledgeBasePanelButton.php b/src/Concerns/HasKnowledgeBasePanelButton.php index 6275701..a05ee77 100644 --- a/src/Concerns/HasKnowledgeBasePanelButton.php +++ b/src/Concerns/HasKnowledgeBasePanelButton.php @@ -49,7 +49,7 @@ protected function getDefaultKnowledgeBasePanelButton(): Action ->icon('heroicon-o-book-open') ->color('gray') ->extraAttributes([ - 'class' => '!font-medium !text-gray-700 dark:!text-gray-200 !mx-4 !mt-2 !mb-4 !py-2.5 !bg-transparent !flex !gap-0 space-x-1.5 !justify-start hover:!bg-gray-100 focus-visible:!bg-gray-100 dark:hover:!bg-white/5 dark:focus-visible:!bg-white/5', + 'class' => '!mx-4 !mb-4 !py-2.5 !flex space-x-1.5 !justify-start', ]) ->url(KnowledgeBase::url( Filament::getPanel($this->getKnowledgeBasePanelId()) diff --git a/src/Plugins/KnowledgeBaseCompanionPlugin.php b/src/Plugins/KnowledgeBaseCompanionPlugin.php index a528bd5..e1d247f 100644 --- a/src/Plugins/KnowledgeBaseCompanionPlugin.php +++ b/src/Plugins/KnowledgeBaseCompanionPlugin.php @@ -90,23 +90,23 @@ public function register(Panel $panel): void fn (Panel $panel) => $panel ->renderHook( PanelsRenderHook::SIDEBAR_FOOTER, - fn (): string => Blade::render('filament-panels::components.sidebar.group', [ - 'attributes' => new ComponentAttributeBag([ - 'class' => 'px-4 pb-4 [&_.fi-sidebar-item]:rounded-lg [&_.fi-sidebar-item]:ring-1 [&_.fi-sidebar-item]:ring-gray-950/10 dark:[&_.fi-sidebar-item]:ring-white/20', - ]), - 'label' => null, - 'items' => [ - NavigationItem::make(__('filament-knowledge-base::translations.knowledge-base')) - ->url(Filament::getPanel($this->getKnowledgeBasePanelId())->getUrl()) - ->icon('heroicon-o-home'), - ], - ]) +// fn (): string => Blade::render('filament-panels::components.sidebar.group', [ +// 'attributes' => new ComponentAttributeBag([ +// 'class' => 'px-4 pb-4 [&_.fi-sidebar-item]:rounded-lg [&_.fi-sidebar-item]:ring-1 [&_.fi-sidebar-item]:ring-gray-950/10 dark:[&_.fi-sidebar-item]:ring-white/20', +// ]), +// 'label' => null, +// 'items' => [ +// NavigationItem::make(__('filament-knowledge-base::translations.knowledge-base')) +// ->url(Filament::getPanel($this->getKnowledgeBasePanelId())->getUrl()) +// ->icon('heroicon-o-home'), +// ], +// ]) // fn (): string => Blade::render('filament-panels::components.sidebar.item', [ // 'url' => '#', // 'icon' => 'heroicon-o-user', // 'slot' => new HtmlString('test'), // ]), - // fn (): string => $this->getKnowledgeBasePanelButton()->render(), + fn (): string => $this->getKnowledgeBasePanelButton()->toHtml(), ) ) // ->renderHook( From 3ad4e1f8d4eefe5d0930d527377d74a76282067c Mon Sep 17 00:00:00 2001 From: Marco Curatitoli Date: Mon, 3 Nov 2025 11:49:35 +0100 Subject: [PATCH 02/33] added fi-not-prose in permalink class --- src/Markdown/MarkdownRenderer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Markdown/MarkdownRenderer.php b/src/Markdown/MarkdownRenderer.php index d865ee8..661a838 100644 --- a/src/Markdown/MarkdownRenderer.php +++ b/src/Markdown/MarkdownRenderer.php @@ -67,7 +67,7 @@ protected function getOptions(): array 'id_prefix' => '', 'symbol' => $anchorSymbol ?? '', 'html_class' => Arr::toCssClasses([ - 'gu-kb-anchor md:absolute md:-left-8 mr-2 md:mr-0 text-primary-600 dark:text-primary-500 font-bold !no-underline -mt-20 pt-20', + 'gu-kb-anchor md:absolute fi-not-prose md:-left-8 mr-2 md:mr-0 text-primary-600 dark:text-primary-500 font-bold !no-underline -mt-20 pt-20', 'hidden' => ! $anchorSymbol, ]), ], From c032d84eacb493e83272b1b0a218c58ed1b84e58 Mon Sep 17 00:00:00 2001 From: Marco Curatitoli Date: Mon, 3 Nov 2025 11:49:56 +0100 Subject: [PATCH 03/33] removed dd from MakeDocumentationCommand.php --- src/Commands/MakeDocumentationCommand.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Commands/MakeDocumentationCommand.php b/src/Commands/MakeDocumentationCommand.php index d5a9cb1..508aeda 100644 --- a/src/Commands/MakeDocumentationCommand.php +++ b/src/Commands/MakeDocumentationCommand.php @@ -4,6 +4,7 @@ use Guava\FilamentKnowledgeBase\KnowledgeBaseRegistry; use Illuminate\Console\GeneratorCommand; +use Illuminate\Support\Arr; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\File; use Illuminate\Support\Stringable; @@ -61,7 +62,6 @@ protected function qualifyClass($name): string public function handle() { - dd(\app(KnowledgeBaseRegistry::class)->getDocsPaths()); $path = str(base_path(config('filament-knowledge-base.docs-path'))) ->rtrim('/') ->append('/') @@ -76,7 +76,7 @@ public function handle() : $locales; if (empty($locales)) { - $locales[] = App::getLocale(); + $locales = Arr::wrap(App::getLocale()); } foreach ($locales as $locale) { From 5cc5037cfae19bdbe64b0f5fbb4b42a72af479a4 Mon Sep 17 00:00:00 2001 From: Marco Curatitoli Date: Mon, 3 Nov 2025 11:50:13 +0100 Subject: [PATCH 04/33] readded missing config entries --- config/filament-knowledge-base.php | 11 +++++++++-- src/KnowledgeBase.php | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/config/filament-knowledge-base.php b/config/filament-knowledge-base.php index d6c43b5..284d16f 100644 --- a/config/filament-knowledge-base.php +++ b/config/filament-knowledge-base.php @@ -2,10 +2,17 @@ // config for Guava/KnowledgeBasePanel return [ - 'flatfile-model' => \Guava\FilamentKnowledgeBase\Models\FlatfileNode::class, + 'panel' => [ + 'id' => env('FILAMENT_KB_ID', 'knowledge-base'), + 'path' => env('FILAMENT_KB_PATH', 'kb'), + ], + + 'docs-path' => env('FILAMENT_KB_DOCS_PATH', 'docs'), + + 'model' => \Guava\FilamentKnowledgeBase\Models\FlatfileNode::class, 'cache' => [ 'prefix' => env('FILAMENT_KB_CACHE_PREFIX', 'filament_kb_'), - 'ttl' => env('FILAMENT_KB_CACHE_TTL', 'forever'), + 'ttl' => env('FILAMENT_KB_CACHE_TTL', 86400), ], ]; diff --git a/src/KnowledgeBase.php b/src/KnowledgeBase.php index 6714095..58b6d49 100755 --- a/src/KnowledgeBase.php +++ b/src/KnowledgeBase.php @@ -15,7 +15,7 @@ class KnowledgeBase { public function model(): Documentable | string { - return config('filament-knowledge-base.flatfile-model'); + return config('filament-knowledge-base.model'); } /** From f95d0b49e78ed9b8f49d230ba21caaf680203dcd Mon Sep 17 00:00:00 2001 From: Marco Curatitoli Date: Mon, 3 Nov 2025 14:51:42 +0100 Subject: [PATCH 05/33] fixed anchor selector --- dist/js/anchors-component.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/js/anchors-component.js b/dist/js/anchors-component.js index c2c0c75..041c0ce 100644 --- a/dist/js/anchors-component.js +++ b/dist/js/anchors-component.js @@ -24,7 +24,7 @@ function anchorsComponent() { if (entry.isIntersecting) { let section = "#" + entry.target.id; document.querySelectorAll(".fi-sidebar-item-button .fi-sidebar-item-label").forEach((el2) => el2.classList.remove(...classes)); - let el = document.querySelector(".fi-sidebar-item-button[href='" + section + "'] .fi-sidebar-item-label"); + let el = document.querySelector(".fi-sidebar-item-btn[href='" + section + "'] .fi-sidebar-item-label"); el.classList.add(...classes); } }); From b60b22359503babad73d9cceb5f4431d3ceaa3b3 Mon Sep 17 00:00:00 2001 From: Marco Curatitoli Date: Wed, 5 Nov 2025 15:26:11 +0100 Subject: [PATCH 06/33] fixed global search --- .../Resources/DocumentationResource.php | 26 +++++++++++++------ src/KnowledgeBase.php | 4 +-- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/Filament/Resources/DocumentationResource.php b/src/Filament/Resources/DocumentationResource.php index 46a2f1e..507d4fd 100644 --- a/src/Filament/Resources/DocumentationResource.php +++ b/src/Filament/Resources/DocumentationResource.php @@ -7,6 +7,7 @@ use Guava\FilamentKnowledgeBase\Facades\KnowledgeBase; use Guava\FilamentKnowledgeBase\Filament\Pages\ViewDocumentation; use Illuminate\Contracts\Support\Htmlable; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; class DocumentationResource extends Resource @@ -18,10 +19,19 @@ public static function getModel(): string public static function getGloballySearchableAttributes(): array { - return ['title', 'content']; + return [ + 'title', + ]; + } + + public static function modifyGlobalSearchQuery(Builder $query, string $search): void + { + $query->orWhereRaw(" + json_extract(data, '$.content') LIKE '%$search%'; + "); } - protected static string | null | \BackedEnum $navigationIcon = 'heroicon-o-rectangle-stack'; + protected static string|null|\BackedEnum $navigationIcon = 'heroicon-o-rectangle-stack'; public static function getPages(): array { @@ -42,19 +52,19 @@ public static function getGlobalSearchResultUrl(Model $record): ?string return ViewDocumentation::getUrl(['record' => $record], panel: KnowledgeBase::panel()->getId()); } - public static function getGlobalSearchResultTitle(Model $record): string | Htmlable + public static function getGlobalSearchResultTitle(Model $record): string|Htmlable { - return str($record->slug) - ->replace('/', ' -> ') - ; + return $record->title; +// return str($record->slug) +// ->replace('/', ' -> '); } - public static function resolveRecordRouteBinding(int | string $key, ?\Closure $modifyQuery = null): ?Model + public static function resolveRecordRouteBinding(int|string $key, ?\Closure $modifyQuery = null): ?Model { // TODO: First try to load it from a standalone (App/Docs) class $record = parent::resolveRecordRouteBinding($key); - if (! $record?->isActive()) { + if (!$record?->isActive()) { return null; } diff --git a/src/KnowledgeBase.php b/src/KnowledgeBase.php index 58b6d49..6f4ec4a 100755 --- a/src/KnowledgeBase.php +++ b/src/KnowledgeBase.php @@ -119,9 +119,9 @@ public function documentable(Documentable | string $documentable): Documentable if ($model = static::model()::query()->find(static::panel()->getId() . '.' . $documentable)) { return $model; - } else { - throw new Exception("'The provided documentable \"$documentable\" could not be found.'"); } + + throw new Exception("'The provided documentable \"$documentable\" could not be found.'"); } public function markdown(Documentable | string $documentable): HtmlString From 84dae68252f3f07c15fec0bcb08b42dd7ec4448a Mon Sep 17 00:00:00 2001 From: Marco Curatitoli Date: Thu, 6 Nov 2025 08:12:01 +0100 Subject: [PATCH 07/33] fixed config file --- config/filament-knowledge-base.php | 9 +-------- src/KnowledgeBase.php | 2 +- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/config/filament-knowledge-base.php b/config/filament-knowledge-base.php index 284d16f..4bf1ead 100644 --- a/config/filament-knowledge-base.php +++ b/config/filament-knowledge-base.php @@ -2,14 +2,7 @@ // config for Guava/KnowledgeBasePanel return [ - 'panel' => [ - 'id' => env('FILAMENT_KB_ID', 'knowledge-base'), - 'path' => env('FILAMENT_KB_PATH', 'kb'), - ], - - 'docs-path' => env('FILAMENT_KB_DOCS_PATH', 'docs'), - - 'model' => \Guava\FilamentKnowledgeBase\Models\FlatfileNode::class, + 'flatfile-model' => \Guava\FilamentKnowledgeBase\Models\FlatfileNode::class, 'cache' => [ 'prefix' => env('FILAMENT_KB_CACHE_PREFIX', 'filament_kb_'), diff --git a/src/KnowledgeBase.php b/src/KnowledgeBase.php index 6f4ec4a..55d1d74 100755 --- a/src/KnowledgeBase.php +++ b/src/KnowledgeBase.php @@ -15,7 +15,7 @@ class KnowledgeBase { public function model(): Documentable | string { - return config('filament-knowledge-base.model'); + return config('filament-knowledge-base.flatfile-model'); } /** From 61790921b675c93dda47f8e47bc083245b1b9e05 Mon Sep 17 00:00:00 2001 From: Marco Curatitoli Date: Thu, 6 Nov 2025 08:54:50 +0100 Subject: [PATCH 08/33] fixed sidebar button --- src/Plugins/KnowledgeBaseCompanionPlugin.php | 27 +++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/Plugins/KnowledgeBaseCompanionPlugin.php b/src/Plugins/KnowledgeBaseCompanionPlugin.php index e1d247f..40e639b 100644 --- a/src/Plugins/KnowledgeBaseCompanionPlugin.php +++ b/src/Plugins/KnowledgeBaseCompanionPlugin.php @@ -90,23 +90,26 @@ public function register(Panel $panel): void fn (Panel $panel) => $panel ->renderHook( PanelsRenderHook::SIDEBAR_FOOTER, -// fn (): string => Blade::render('filament-panels::components.sidebar.group', [ -// 'attributes' => new ComponentAttributeBag([ -// 'class' => 'px-4 pb-4 [&_.fi-sidebar-item]:rounded-lg [&_.fi-sidebar-item]:ring-1 [&_.fi-sidebar-item]:ring-gray-950/10 dark:[&_.fi-sidebar-item]:ring-white/20', -// ]), -// 'label' => null, -// 'items' => [ -// NavigationItem::make(__('filament-knowledge-base::translations.knowledge-base')) -// ->url(Filament::getPanel($this->getKnowledgeBasePanelId())->getUrl()) -// ->icon('heroicon-o-home'), -// ], -// ]) + fn (): string => Blade::render('filament-panels::components.sidebar.group', [ + 'attributes' => new ComponentAttributeBag([ + 'class' => 'px-4 pb-4 [&_.fi-sidebar-item]:rounded-lg [&_.fi-sidebar-item]:ring-1 [&_.fi-sidebar-item]:ring-gray-950/10 dark:[&_.fi-sidebar-item]:ring-white/20', + ]), + 'label' => null, + 'items' => [ + NavigationItem::make(__('filament-knowledge-base::translations.knowledge-base')) + ->url( + Filament::getPanel($this->getKnowledgeBasePanelId())->getUrl(), + $this->shouldOpenKnowledgeBasePanelInNewTab() + ) + ->icon('heroicon-o-book-open'), + ], + ]) // fn (): string => Blade::render('filament-panels::components.sidebar.item', [ // 'url' => '#', // 'icon' => 'heroicon-o-user', // 'slot' => new HtmlString('test'), // ]), - fn (): string => $this->getKnowledgeBasePanelButton()->toHtml(), +// fn (): string => $this->getKnowledgeBasePanelButton()->toHtml(), ) ) // ->renderHook( From 2c46229b65c7cd600087542e61c212e8d439930a Mon Sep 17 00:00:00 2001 From: Marco Curatitoli Date: Fri, 7 Nov 2025 10:01:31 +0100 Subject: [PATCH 09/33] removed fi-not-prose in permalink class --- src/Markdown/MarkdownRenderer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Markdown/MarkdownRenderer.php b/src/Markdown/MarkdownRenderer.php index 661a838..d865ee8 100644 --- a/src/Markdown/MarkdownRenderer.php +++ b/src/Markdown/MarkdownRenderer.php @@ -67,7 +67,7 @@ protected function getOptions(): array 'id_prefix' => '', 'symbol' => $anchorSymbol ?? '', 'html_class' => Arr::toCssClasses([ - 'gu-kb-anchor md:absolute fi-not-prose md:-left-8 mr-2 md:mr-0 text-primary-600 dark:text-primary-500 font-bold !no-underline -mt-20 pt-20', + 'gu-kb-anchor md:absolute md:-left-8 mr-2 md:mr-0 text-primary-600 dark:text-primary-500 font-bold !no-underline -mt-20 pt-20', 'hidden' => ! $anchorSymbol, ]), ], From dcc9c4214b7f5d1d3ac3d1a53e37d998e7fb732e Mon Sep 17 00:00:00 2001 From: Marco Curatitoli Date: Fri, 7 Nov 2025 10:01:56 +0100 Subject: [PATCH 10/33] added default icons to config --- config/filament-knowledge-base.php | 8 ++++++++ src/KnowledgeBase.php | 2 +- src/Models/FlatfileNode.php | 14 ++++++++------ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/config/filament-knowledge-base.php b/config/filament-knowledge-base.php index 4bf1ead..2ee8b90 100644 --- a/config/filament-knowledge-base.php +++ b/config/filament-knowledge-base.php @@ -1,6 +1,8 @@ \Guava\FilamentKnowledgeBase\Models\FlatfileNode::class, @@ -8,4 +10,10 @@ 'prefix' => env('FILAMENT_KB_CACHE_PREFIX', 'filament_kb_'), 'ttl' => env('FILAMENT_KB_CACHE_TTL', 86400), ], + + 'icons' => [ + NodeType::Documentation->value => 'heroicon-o-document', + NodeType::Link->value => 'heroicon-o-link', + NodeType::Group->value => null, + ] ]; diff --git a/src/KnowledgeBase.php b/src/KnowledgeBase.php index 55d1d74..82fc126 100755 --- a/src/KnowledgeBase.php +++ b/src/KnowledgeBase.php @@ -117,7 +117,7 @@ public function documentable(Documentable | string $documentable): Documentable return $documentable; } - if ($model = static::model()::query()->find(static::panel()->getId() . '.' . $documentable)) { + if ($model = $this->model()::query()->find($this->panel()->getId() . '.' . $documentable)) { return $model; } diff --git a/src/Models/FlatfileNode.php b/src/Models/FlatfileNode.php index 87aa155..219c9ff 100644 --- a/src/Models/FlatfileNode.php +++ b/src/Models/FlatfileNode.php @@ -14,6 +14,7 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\Arr; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\File; use League\CommonMark\Extension\HeadingPermalink\HeadingPermalink; @@ -187,7 +188,7 @@ public function toNavigationItem(): NavigationItem return $item; } - public function toNavigationGroup(bool $canHaveIcon = true): NavigationGroup + public function toNavigationGroup(): NavigationGroup { if ($this->type !== NodeType::Group) { throw new \Exception('Cannot convert a document to a navigation group'); @@ -195,8 +196,7 @@ public function toNavigationGroup(bool $canHaveIcon = true): NavigationGroup $canHaveIcon = $this ->children()->where(fn (FlatfileNode $child) => $child->children()->isNotEmpty()) - ->isEmpty() - ; + ->isEmpty(); return NavigationGroup::make($this->getTitle()) ->icon($canHaveIcon ? $this->getIcon() : null) @@ -281,10 +281,12 @@ public function getRouteKeyName(): string protected function getDefaultIcon(): ?string { + $icons = config('filament-knowledge-base.icons'); + return match ($this->getType()) { - NodeType::Documentation => 'heroicon-o-document', - NodeType::Link => 'heroicon-o-link', - NodeType::Group => null, + NodeType::Documentation => Arr::get($icons, NodeType::Documentation->value, 'heroicon-o-document'), + NodeType::Link => Arr::get($icons, NodeType::Link->value, 'heroicon-o-link'), + NodeType::Group => Arr::get($icons, NodeType::Group->value), }; } } From 6a5f3e746d2f625ff47c8bc9385ecaecb4105da0 Mon Sep 17 00:00:00 2001 From: Marco Curatitoli Date: Fri, 7 Nov 2025 13:13:05 +0100 Subject: [PATCH 11/33] added italian traslation --- resources/lang/it/translations.php | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 resources/lang/it/translations.php diff --git a/resources/lang/it/translations.php b/resources/lang/it/translations.php new file mode 100644 index 0000000..626867d --- /dev/null +++ b/resources/lang/it/translations.php @@ -0,0 +1,11 @@ + 'Documentazione', + 'help' => 'Aiuto', + 'open-documentation' => 'Apri documentazione', + 'close' => 'Chiudi', + 'back-to-default-panel' => 'Indietro', + 'url-copied' => 'La URL è stata copiata nei tuoi appunti.', + 'code-copied' => 'Il codice è stato copiato nei tuoi appunti.', +]; From 1b814d260e0ea0d8e1115f75ebbe59fcab9fff5e Mon Sep 17 00:00:00 2001 From: Marco Curatitoli Date: Fri, 7 Nov 2025 18:19:45 +0100 Subject: [PATCH 12/33] fixed global search --- src/Filament/Resources/DocumentationResource.php | 14 ++++++++------ src/Models/FlatfileNode.php | 2 +- src/Support/FlatfileParser.php | 5 ++--- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Filament/Resources/DocumentationResource.php b/src/Filament/Resources/DocumentationResource.php index 507d4fd..f6e92f2 100644 --- a/src/Filament/Resources/DocumentationResource.php +++ b/src/Filament/Resources/DocumentationResource.php @@ -21,15 +21,17 @@ public static function getGloballySearchableAttributes(): array { return [ 'title', + 'data' ]; } - public static function modifyGlobalSearchQuery(Builder $query, string $search): void - { - $query->orWhereRaw(" - json_extract(data, '$.content') LIKE '%$search%'; - "); - } +// public static function modifyGlobalSearchQuery(Builder $query, string $search): void +// { +//// $query->orWhereRaw(" +//// json_extract(data, '$.content') LIKE '%$search%'; +//// "); +// $query->orWhereLike('data', "%$search%"); +// } protected static string|null|\BackedEnum $navigationIcon = 'heroicon-o-rectangle-stack'; diff --git a/src/Models/FlatfileNode.php b/src/Models/FlatfileNode.php index 219c9ff..056f8ba 100644 --- a/src/Models/FlatfileNode.php +++ b/src/Models/FlatfileNode.php @@ -36,7 +36,7 @@ class FlatfileNode extends Model implements Documentable 'title' => 'string', 'order' => 'integer', 'active' => 'boolean', - 'data' => 'json', + 'data' => 'string', 'parent_id' => 'string', 'panel_id' => 'string', ]; diff --git a/src/Support/FlatfileParser.php b/src/Support/FlatfileParser.php index 4f9e482..13ac138 100644 --- a/src/Support/FlatfileParser.php +++ b/src/Support/FlatfileParser.php @@ -141,7 +141,7 @@ protected function parseGroupFile(SplFileInfo $file, string $id, Fluent $data, b protected function processDocumentationFile(SplFileInfo $file, string $id, Fluent $data, bool $checkParents = false): array { $result = [ - 'data' => json_encode([ + 'data' => serialize([ ...$this->getCustomData($data), 'content' => $data->get('html'), ]), @@ -191,8 +191,7 @@ protected function getCustomData(Fluent $data): array 'data', 'content', ]) - ->all() - ; + ->all(); } public function renderer(string $renderer): static From 250a78db8e8feb54db0de1918e9bbcde0c208569 Mon Sep 17 00:00:00 2001 From: Marco Curatitoli Date: Mon, 10 Nov 2025 09:21:39 +0100 Subject: [PATCH 13/33] use current selected locale --- src/Plugins/KnowledgeBasePlugin.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Plugins/KnowledgeBasePlugin.php b/src/Plugins/KnowledgeBasePlugin.php index d6589b3..cedb5ed 100644 --- a/src/Plugins/KnowledgeBasePlugin.php +++ b/src/Plugins/KnowledgeBasePlugin.php @@ -3,6 +3,7 @@ namespace Guava\FilamentKnowledgeBase\Plugins; use Filament\Contracts\Plugin; +use Filament\Facades\Filament; use Filament\Panel; use Filament\Support\Concerns\EvaluatesClosures; use Filament\View\PanelsRenderHook; @@ -72,7 +73,10 @@ public function register(Panel $panel): void public function boot(Panel $panel): void { - Navigation::make($panel)->build(); + // Defer building navigation until Filament is serving a request to avoid early model autoloading + Filament::serving(function () use ($panel) { + Navigation::make($panel)->build(); + }); } public static function make(?string $docsPath = null): static From 10efd805dbe04ff4d9d78cc424927f60e3e8c30e Mon Sep 17 00:00:00 2001 From: Marco Curatitoli Date: Thu, 13 Nov 2025 16:09:29 +0100 Subject: [PATCH 14/33] process only markdown files --- src/Support/FlatfileParser.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Support/FlatfileParser.php b/src/Support/FlatfileParser.php index 13ac138..514b4be 100644 --- a/src/Support/FlatfileParser.php +++ b/src/Support/FlatfileParser.php @@ -25,6 +25,7 @@ public function __construct( public function get(): Collection { collect(File::allFiles($this->path)) + ->filter(fn (SplFileInfo $file) => in_array(strtolower($file->getExtension()), ['md', 'markdown'])) ->each(fn (SplFileInfo $file) => $this->processFile($file)) ; From 99a11dc625d70968bf6a4625bde2ff54ae325d7d Mon Sep 17 00:00:00 2001 From: pimeo Date: Fri, 28 Nov 2025 19:15:14 +0100 Subject: [PATCH 15/33] wip: documentable method allow to use custom panel id --- src/KnowledgeBase.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/KnowledgeBase.php b/src/KnowledgeBase.php index 6714095..dcf5af9 100755 --- a/src/KnowledgeBase.php +++ b/src/KnowledgeBase.php @@ -111,13 +111,17 @@ public function url(Panel $panel): ?string return $url; } - public function documentable(Documentable | string $documentable): Documentable + public function documentable(Documentable | string $documentable, ?string $panelId = null): Documentable { if ($documentable instanceof Documentable) { return $documentable; } - if ($model = static::model()::query()->find(static::panel()->getId() . '.' . $documentable)) { + if (is_null($panelId) || $panelId === '') { + $panelId = static::panel()->getId(); + } + + if ($model = static::model()::query()->find($panelId . '.' . $documentable)) { return $model; } else { throw new Exception("'The provided documentable \"$documentable\" could not be found.'"); From a32d3dbf5bb58c4f5cfdd461fd32a6eb1a0123e5 Mon Sep 17 00:00:00 2001 From: pimeo Date: Fri, 28 Nov 2025 19:21:06 +0100 Subject: [PATCH 16/33] wip: take in account panel id choice to help actions components and action --- src/Actions/Forms/Components/HelpAction.php | 14 +++++++------- src/Actions/HelpAction.php | 14 +++++++------- src/Actions/Tables/Components/HelpAction.php | 14 +++++++------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Actions/Forms/Components/HelpAction.php b/src/Actions/Forms/Components/HelpAction.php index 5b3b285..a33b91f 100644 --- a/src/Actions/Forms/Components/HelpAction.php +++ b/src/Actions/Forms/Components/HelpAction.php @@ -31,26 +31,26 @@ protected static function getContentView(Documentable $documentable): HtmlString return new HtmlString(\Str::replace($replacementStringId, $html, $parsed)); } - public static function forDocumentable(Documentable | string $documentable): static + public static function forDocumentable(Documentable | string $documentable, ?string $panelId = null): static { - $documentable = KnowledgeBase::documentable($documentable); + $documentable = KnowledgeBase::documentable($documentable, $panelId); return static::make("help.{$documentable->getId()}") ->label($documentable->getTitle()) -// ->icon($documentable->getIcon()) + // ->icon($documentable->getIcon()) ->icon('heroicon-o-question-mark-circle') ->when( KnowledgeBase::companion()->hasModalPreviews(), - fn (HelpAction $action) => $action - ->modalContent(fn () => static::getContentView($documentable)) + fn(HelpAction $action) => $action + ->modalContent(fn() => static::getContentView($documentable)) ->modalHeading($documentable->getTitle()) ->modalSubmitAction(false) ->modalCancelActionLabel(__('filament-knowledge-base::translations.close')) ->when( KnowledgeBase::companion()->hasSlideOverPreviews(), - fn (HelpAction $action) => $action->slideOver() + fn(HelpAction $action) => $action->slideOver() ), - fn (HelpAction $action) => $action->url($documentable->getUrl()) + fn(HelpAction $action) => $action->url($documentable->getUrl()) ) ; } diff --git a/src/Actions/HelpAction.php b/src/Actions/HelpAction.php index 9ac9447..b175599 100644 --- a/src/Actions/HelpAction.php +++ b/src/Actions/HelpAction.php @@ -21,25 +21,25 @@ public function generic(): HelpAction ; } - public static function forDocumentable(Documentable | string $documentable): HelpAction + public static function forDocumentable(Documentable | string $documentable, ?string $panelId = null): HelpAction { - $documentable = KnowledgeBase::documentable($documentable); + $documentable = KnowledgeBase::documentable($documentable, $panelId); return static::make("help.{$documentable->getId()}") ->label($documentable->getTitle()) ->icon($documentable->getIcon()) ->when( KnowledgeBase::companion()->hasModalPreviews(), - fn (HelpAction $action) => $action + fn(HelpAction $action) => $action ->modal() ->modalContent(new HtmlString('test')) - ->action(fn () => dd('test')) -// ->alpineClickHandler('$dispatch(\"open-modal\", {id: "' . $documentable->getId() . '"})') + ->action(fn() => dd('test')) + // ->alpineClickHandler('$dispatch(\"open-modal\", {id: "' . $documentable->getId() . '"})') ->when( KnowledgeBase::companion()->hasSlideOverPreviews(), - fn (HelpAction $action) => $action->slideOver() + fn(HelpAction $action) => $action->slideOver() ), - fn (HelpAction $action) => $action->url($documentable->getUrl()) + fn(HelpAction $action) => $action->url($documentable->getUrl()) ) ; } diff --git a/src/Actions/Tables/Components/HelpAction.php b/src/Actions/Tables/Components/HelpAction.php index c690bf5..1de06ec 100644 --- a/src/Actions/Tables/Components/HelpAction.php +++ b/src/Actions/Tables/Components/HelpAction.php @@ -31,26 +31,26 @@ protected static function getContentView(Documentable $documentable): HtmlString return new HtmlString(\Str::replace($replacementStringId, $html, $parsed)); } - public static function forDocumentable(Documentable | string $documentable): static + public static function forDocumentable(Documentable | string $documentable, ?string $panelId = null): static { - $documentable = KnowledgeBase::documentable($documentable); + $documentable = KnowledgeBase::documentable($documentable, $panelId); return static::make("help.{$documentable->getId()}") ->label($documentable->getTitle()) -// ->icon($documentable->getIcon()) + // ->icon($documentable->getIcon()) ->icon('heroicon-o-question-mark-circle') ->when( KnowledgeBase::companion()->hasModalPreviews(), - fn (HelpAction $action) => $action - ->modalContent(fn () => static::getContentView($documentable)) + fn(HelpAction $action) => $action + ->modalContent(fn() => static::getContentView($documentable)) ->modalHeading($documentable->getTitle()) ->modalSubmitAction(false) ->modalCancelActionLabel(__('filament-knowledge-base::translations.close')) ->when( KnowledgeBase::companion()->hasSlideOverPreviews(), - fn (HelpAction $action) => $action->slideOver() + fn(HelpAction $action) => $action->slideOver() ), - fn (HelpAction $action) => $action->url($documentable->getUrl()) + fn(HelpAction $action) => $action->url($documentable->getUrl()) ) ; } From 8809bcf7d01199d23c31b49da9f81582ed5d19bf Mon Sep 17 00:00:00 2001 From: pimeo Date: Fri, 28 Nov 2025 23:57:53 +0100 Subject: [PATCH 17/33] fix: helper action render documentable html contents --- resources/lang/fr/translations.php | 4 ++-- src/Actions/HelpAction.php | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/resources/lang/fr/translations.php b/resources/lang/fr/translations.php index 1125ba0..4a77003 100644 --- a/resources/lang/fr/translations.php +++ b/resources/lang/fr/translations.php @@ -6,6 +6,6 @@ 'open-documentation' => 'Ouvrir la documentation', 'close' => 'Fermer', 'back-to-default-panel' => 'Retour', - 'url-copied' => 'URL copiée dans votre presse-papiers.', - 'code-copied' => 'Code copié dans votre presse-papiers.', + 'url-copied' => 'URL copiée dans votre presse-papier.', + 'code-copied' => 'Code copié dans votre presse-papier.', ]; diff --git a/src/Actions/HelpAction.php b/src/Actions/HelpAction.php index b175599..c2681f5 100644 --- a/src/Actions/HelpAction.php +++ b/src/Actions/HelpAction.php @@ -24,7 +24,6 @@ public function generic(): HelpAction public static function forDocumentable(Documentable | string $documentable, ?string $panelId = null): HelpAction { $documentable = KnowledgeBase::documentable($documentable, $panelId); - return static::make("help.{$documentable->getId()}") ->label($documentable->getTitle()) ->icon($documentable->getIcon()) @@ -32,9 +31,13 @@ public static function forDocumentable(Documentable | string $documentable, ?str KnowledgeBase::companion()->hasModalPreviews(), fn(HelpAction $action) => $action ->modal() - ->modalContent(new HtmlString('test')) - ->action(fn() => dd('test')) - // ->alpineClickHandler('$dispatch(\"open-modal\", {id: "' . $documentable->getId() . '"})') + ->modalContent(function () use ($documentable) { + $content = data_get($documentable->getData(), 'content', ''); + $body = new HtmlString("
{$content}
"); + return $body; + }) + ->modalCancelActionLabel(__('filament-knowledge-base::translations.close')) + ->modalSubmitAction(false) ->when( KnowledgeBase::companion()->hasSlideOverPreviews(), fn(HelpAction $action) => $action->slideOver() From 0d45af06a286359da5232eaa9468b6dd6bd68259 Mon Sep 17 00:00:00 2001 From: pimeo Date: Fri, 28 Nov 2025 23:59:49 +0100 Subject: [PATCH 18/33] fix: inherits from setUp method to avoid missing action view --- src/Actions/HelpAction.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Actions/HelpAction.php b/src/Actions/HelpAction.php index c2681f5..73bf403 100644 --- a/src/Actions/HelpAction.php +++ b/src/Actions/HelpAction.php @@ -9,7 +9,10 @@ class HelpAction extends Action { - protected function setUp(): void {} + protected function setUp(): void + { + parent::setUp(); + } public function generic(): HelpAction { From 0c618d12d215309ec3c49b1c137d4db68eb65cdf Mon Sep 17 00:00:00 2001 From: pimeo Date: Sat, 29 Nov 2025 00:17:48 +0100 Subject: [PATCH 19/33] feat: modal support heading --- src/Actions/HelpAction.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Actions/HelpAction.php b/src/Actions/HelpAction.php index 73bf403..60eb65d 100644 --- a/src/Actions/HelpAction.php +++ b/src/Actions/HelpAction.php @@ -33,7 +33,9 @@ public static function forDocumentable(Documentable | string $documentable, ?str ->when( KnowledgeBase::companion()->hasModalPreviews(), fn(HelpAction $action) => $action - ->modal() + ->modalHeading(function () use ($documentable) { + return new HtmlString("

{$documentable->getTitle()}

"); + }) ->modalContent(function () use ($documentable) { $content = data_get($documentable->getData(), 'content', ''); $body = new HtmlString("
{$content}
"); From 2e69764b2daedc6e6c261e16120407c15a25f6aa Mon Sep 17 00:00:00 2001 From: Leo Lutz Date: Sat, 6 Dec 2025 16:28:44 -0700 Subject: [PATCH 20/33] Fix the link on heading permalinks Fixes #95. --- src/Markdown/MarkdownRenderer.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Markdown/MarkdownRenderer.php b/src/Markdown/MarkdownRenderer.php index d865ee8..90c30a2 100644 --- a/src/Markdown/MarkdownRenderer.php +++ b/src/Markdown/MarkdownRenderer.php @@ -65,6 +65,7 @@ protected function getOptions(): array ], 'heading_permalink' => [ 'id_prefix' => '', + 'fragment_prefix' => '', 'symbol' => $anchorSymbol ?? '', 'html_class' => Arr::toCssClasses([ 'gu-kb-anchor md:absolute md:-left-8 mr-2 md:mr-0 text-primary-600 dark:text-primary-500 font-bold !no-underline -mt-20 pt-20', From 708b9305bf5467da06853a528f0520cfbdb6e3ff Mon Sep 17 00:00:00 2001 From: Leo Lutz Date: Sat, 6 Dec 2025 16:51:21 -0700 Subject: [PATCH 21/33] Fix the template path in the CSS instructions Not all styles were getting added because the path to the views directory is wrong. --- docs/v2/introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/v2/introduction.md b/docs/v2/introduction.md index 5e00e99..93a00b1 100644 --- a/docs/v2/introduction.md +++ b/docs/v2/introduction.md @@ -57,7 +57,7 @@ And lastly, add the following to your custom filament theme to correctly build t ```css @plugin "@tailwindcss/typography"; @source '../../../../vendor/guava/filament-knowledge-base/src/**/*'; -@source '../../../../vendor/guava/filament-knowledge-base/resources/view/**/*'; +@source '../../../../vendor/guava/filament-knowledge-base/resources/views/**/*'; ``` > [!IMPORTANT] From dad339cff8153b4b86cd324a7f5195d881404c51 Mon Sep 17 00:00:00 2001 From: Leo Lutz Date: Sat, 6 Dec 2025 19:08:09 -0700 Subject: [PATCH 22/33] Match PHP version to the minimum allowed in v2 and add the pdo_sqlite extension --- .github/workflows/phpstan.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml index ccfa9d9..a3a4bab 100644 --- a/.github/workflows/phpstan.yml +++ b/.github/workflows/phpstan.yml @@ -16,7 +16,8 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.1' + extensions: pdo_sqlite + php-version: '8.2' coverage: none - name: Install composer dependencies From 760079f5d85c17e425acd2c60f1518578789ded1 Mon Sep 17 00:00:00 2001 From: Leo Lutz Date: Sat, 6 Dec 2025 19:17:46 -0700 Subject: [PATCH 23/33] Upgrade to larastan/larastan --- composer.json | 6 ++---- phpstan.neon.dist | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index 0e016f7..b8ecf0d 100644 --- a/composer.json +++ b/composer.json @@ -28,14 +28,13 @@ "symfony/yaml": "^7.0" }, "require-dev": { + "larastan/larastan": "^2.11", "laravel/pint": "^1.0", "nunomaduro/collision": "^8.0", - "nunomaduro/larastan": "^2.0.1", "orchestra/testbench": "^9.0|^10.0", "pestphp/pest": "^2.0", "pestphp/pest-plugin-arch": "^2.0", "pestphp/pest-plugin-laravel": "^2.0", - "phpstan/extension-installer": "^1.1", "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-phpunit": "^1.0" }, @@ -72,8 +71,7 @@ "config": { "sort-packages": true, "allow-plugins": { - "pestphp/pest-plugin": true, - "phpstan/extension-installer": true + "pestphp/pest-plugin": true } }, "extra": { diff --git a/phpstan.neon.dist b/phpstan.neon.dist index aeda032..8df2ff9 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,6 +1,6 @@ includes: - phpstan-baseline.neon - - ./vendor/nunomaduro/larastan/extension.neon + - vendor/larastan/larastan/extension.neon parameters: level: 4 From fa18487021f0bff51329fd70931e4aaa60b810cb Mon Sep 17 00:00:00 2001 From: Leo Lutz Date: Sat, 6 Dec 2025 19:19:46 -0700 Subject: [PATCH 24/33] Remove deprecated parameter I replaced it with the new style, but it wasn't an error found, so I removed it completely. --- phpstan.neon.dist | 2 -- 1 file changed, 2 deletions(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 8df2ff9..d00ec24 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -11,5 +11,3 @@ parameters: tmpDir: build/phpstan checkOctaneCompatibility: true checkModelProperties: true - checkMissingIterableValueType: false - From 57c4c8691f76057a2be9a682826eeb2a705b6bad Mon Sep 17 00:00:00 2001 From: Leo Lutz Date: Sat, 6 Dec 2025 20:06:23 -0700 Subject: [PATCH 25/33] Upgrade PestPHP to 3 so it covers 11|12. Upgrade Larastan to match. --- composer.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index b8ecf0d..697fc31 100644 --- a/composer.json +++ b/composer.json @@ -28,15 +28,15 @@ "symfony/yaml": "^7.0" }, "require-dev": { - "larastan/larastan": "^2.11", + "larastan/larastan": "^3.0", "laravel/pint": "^1.0", "nunomaduro/collision": "^8.0", "orchestra/testbench": "^9.0|^10.0", - "pestphp/pest": "^2.0", - "pestphp/pest-plugin-arch": "^2.0", - "pestphp/pest-plugin-laravel": "^2.0", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-phpunit": "^1.0" + "pestphp/pest": "^3.0", + "pestphp/pest-plugin-arch": "^3.0", + "pestphp/pest-plugin-laravel": "^3.0", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-phpunit": "^2.0" }, "autoload": { "psr-4": { From b600a96849278d98202db41bdd65c13dc3ad8819 Mon Sep 17 00:00:00 2001 From: Leo Lutz Date: Sat, 6 Dec 2025 20:09:52 -0700 Subject: [PATCH 26/33] Upgrade the matrix to match current requirements. Attempting removal of the Testbench version since it should be auto-resolved. --- .github/workflows/run-tests.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 7fefe35..c50c55d 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -13,13 +13,12 @@ jobs: fail-fast: true matrix: os: [ubuntu-latest, windows-latest] - php: [8.2, 8.1] - laravel: [10.*] + php: [8.2, 8.4] + laravel: [11.*, 12.*] stability: [prefer-lowest, prefer-stable] include: - - laravel: 10.* - testbench: 8.* - carbon: ^2.63 + - laravel: 11.* + - laravel: 12.* name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }} From 3f524f81b9abd4d84c06bf66d276436c29e15c66 Mon Sep 17 00:00:00 2001 From: Leo Lutz Date: Sat, 6 Dec 2025 20:10:23 -0700 Subject: [PATCH 27/33] Update the service provider name to V2. --- tests/TestCase.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/TestCase.php b/tests/TestCase.php index e4e19fd..78ddc27 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -2,7 +2,7 @@ namespace Guava\FilamentKnowledgeBase\Tests; -use Guava\FilamentKnowledgeBase\FilamentKnowledgeBaseServiceProvider; +use Guava\FilamentKnowledgeBase\KnowledgeBaseServiceProvider; use Illuminate\Database\Eloquent\Factories\Factory; use Orchestra\Testbench\TestCase as Orchestra; @@ -20,7 +20,7 @@ protected function setUp(): void protected function getPackageProviders($app) { return [ - FilamentKnowledgeBaseServiceProvider::class, + KnowledgeBaseServiceProvider::class, ]; } From ffe7665e91322e7501d1387f8d61153493cb65b2 Mon Sep 17 00:00:00 2001 From: Leo Lutz Date: Sat, 6 Dec 2025 20:12:39 -0700 Subject: [PATCH 28/33] Restore Testbench versions since they didn't autoinstall. --- .github/workflows/run-tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index c50c55d..a932954 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -18,7 +18,9 @@ jobs: stability: [prefer-lowest, prefer-stable] include: - laravel: 11.* + testbench: 9.* - laravel: 12.* + testbench: 10.* name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }} From 4fd622b0a99a2beaebcb8a2f2089e266dd376245 Mon Sep 17 00:00:00 2001 From: Leo Lutz Date: Sat, 6 Dec 2025 20:17:51 -0700 Subject: [PATCH 29/33] Restore carbon versions --- .github/workflows/run-tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index a932954..94cf9b3 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -19,8 +19,10 @@ jobs: include: - laravel: 11.* testbench: 9.* + carbon: ^2.63 - laravel: 12.* testbench: 10.* + carbon: ^3.8.4 name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }} From 07b7196302e66123b4dde938a9d60cd6e98bfd3f Mon Sep 17 00:00:00 2001 From: Lukas Frey Date: Sun, 7 Dec 2025 11:46:22 +0100 Subject: [PATCH 30/33] fix: make documentation command Signed-off-by: Lukas Frey --- src/Commands/MakeDocumentationCommand.php | 127 +++++++++++++++------- 1 file changed, 90 insertions(+), 37 deletions(-) diff --git a/src/Commands/MakeDocumentationCommand.php b/src/Commands/MakeDocumentationCommand.php index 508aeda..d0ceef0 100644 --- a/src/Commands/MakeDocumentationCommand.php +++ b/src/Commands/MakeDocumentationCommand.php @@ -2,16 +2,22 @@ namespace Guava\FilamentKnowledgeBase\Commands; -use Guava\FilamentKnowledgeBase\KnowledgeBaseRegistry; +use Filament\Facades\Filament; +use Filament\Panel; +use Guava\FilamentKnowledgeBase\Plugins\KnowledgeBasePlugin; use Illuminate\Console\GeneratorCommand; use Illuminate\Support\Arr; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\File; use Illuminate\Support\Stringable; +use function Laravel\Prompts\error; +use function Laravel\Prompts\select; +use function Laravel\Prompts\text; + class MakeDocumentationCommand extends GeneratorCommand { - protected $signature = 'docs:make {panel} {name} {--L|locale=*}'; + protected $signature = 'docs:make {panel?} {name?} {--L|locale=*}'; protected $aliases = [ 'kb:make', @@ -21,6 +27,10 @@ class MakeDocumentationCommand extends GeneratorCommand protected $type = 'Documentation'; + protected ?string $panelId = null; + + protected ?string $docsId = null; + protected function getStub(): string { return __DIR__ . '/../../stubs/markdown.md.stub'; @@ -31,48 +41,91 @@ protected function qualifyClass($name): string return $name; } - // protected function getPath($name) - // { - // dd(\app(KnowledgeBaseRegistry::class)->getDocsPaths()); - // return str(base_path(config('filament-knowledge-base.docs-path'))) - // ->rtrim('/') - // ->append( - // '/', - // str($name) - // ->replaceEnd('.md', '') - // ->append('.md') - // ) - // ; - // } - - // protected function getNameInput() - // { - // return str(parent::getNameInput()) - // ->trim('/') - // ->replace('.', '/') - // ->when( - // ! $this->option('class'), - // fn (Stringable $str) => $str->prepend($this->currentLocale, '/') - // ) - // ->toString() - // ; - // } - - protected string $currentLocale; - - public function handle() + protected function getPath($name): string { - $path = str(base_path(config('filament-knowledge-base.docs-path'))) + return str($this->getDocsPath()) ->rtrim('/') - ->append('/') + ->when( + $this->currentLocale, + fn (Stringable $str) => $str + ->append( + '/', + $this->currentLocale + ) + ) + ->append( + '/', + str($name) + ->replaceEnd('.md', '') + ->append('.md') + ) + ; + } + + protected function getDocsPath(): string + { + /** @var KnowledgeBasePlugin $plugin */ + $plugin = Filament::getPanel($this->panelId)->getPlugin(KnowledgeBasePlugin::ID); + + return $plugin->getDocsPath(); + } + + protected function getNameInput(): string + { + return str($this->docsId) + ->trim('/') + ->replace('.', '/') ->toString() ; - if (! File::exists($path)) { - File::makeDirectory($path); + } + + protected ?string $currentLocale = null; + + public function handle(): bool + { + $knowledgeBasePanels = collect(Filament::getPanels()) + ->filter(static fn (Panel $panel) => $panel->hasPlugin(KnowledgeBasePlugin::ID)) + ->keys() + ; + + if ($knowledgeBasePanels->isEmpty()) { + error('Please create a knowledge base panel first.'); + + return false; + } + + $this->panelId = $knowledgeBasePanels->count() > 1 + ? select( + label: 'Which knowledge base panel do you want to add a documentation page to?', + options: $knowledgeBasePanels, + required: true + ) + : $knowledgeBasePanels->first(); + + $this->docsId = text( + label: 'Enter the ID of the documentation page in dot-notation:', + placeholder: 'Such as "users.introduction"', + required: true, + validate: ['name' => 'required|regex:/^[\w\-\.]+$/i'] + ); + + if (count(explode('.', $this->docsId)) > 3) { + error('You can nest documentations only 3 levels deep!'); + + return false; + } + + $docsPath = $this->getDocsPath(); + // Create docs path if not existing + if (! File::exists($docsPath)) { + File::makeDirectory( + path: $docsPath, + recursive: true + ); } $locales = $this->option('locale'); $locales = empty($locales) - ? File::directories($path) + ? File::directories($docsPath) : $locales; if (empty($locales)) { From 8fc425fe4408833eb758041cbb9f31000234bef1 Mon Sep 17 00:00:00 2001 From: Lukas Frey Date: Sun, 7 Dec 2025 12:05:18 +0100 Subject: [PATCH 31/33] fix: make documentation command Signed-off-by: Lukas Frey --- src/Commands/MakeDocumentationCommand.php | 31 ++++++++++++++++++++--- stubs/documentation.md.stub | 4 +++ stubs/group.md.stub | 4 +++ stubs/link.md.stub | 5 ++++ stubs/markdown.md.stub | 4 --- 5 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 stubs/documentation.md.stub create mode 100644 stubs/group.md.stub create mode 100644 stubs/link.md.stub delete mode 100644 stubs/markdown.md.stub diff --git a/src/Commands/MakeDocumentationCommand.php b/src/Commands/MakeDocumentationCommand.php index d0ceef0..778cd85 100644 --- a/src/Commands/MakeDocumentationCommand.php +++ b/src/Commands/MakeDocumentationCommand.php @@ -4,6 +4,7 @@ use Filament\Facades\Filament; use Filament\Panel; +use Guava\FilamentKnowledgeBase\Enums\NodeType; use Guava\FilamentKnowledgeBase\Plugins\KnowledgeBasePlugin; use Illuminate\Console\GeneratorCommand; use Illuminate\Support\Arr; @@ -11,13 +12,14 @@ use Illuminate\Support\Facades\File; use Illuminate\Support\Stringable; +use function Laravel\Prompts\info; use function Laravel\Prompts\error; use function Laravel\Prompts\select; use function Laravel\Prompts\text; class MakeDocumentationCommand extends GeneratorCommand { - protected $signature = 'docs:make {panel?} {name?} {--L|locale=*}'; + protected $signature = 'docs:make {panel?} {type?} {name?} {--L|locale=*}'; protected $aliases = [ 'kb:make', @@ -27,13 +29,19 @@ class MakeDocumentationCommand extends GeneratorCommand protected $type = 'Documentation'; + protected NodeType $nodeType = NodeType::Documentation; + protected ?string $panelId = null; protected ?string $docsId = null; protected function getStub(): string { - return __DIR__ . '/../../stubs/markdown.md.stub'; + return match ($this->nodeType) { + NodeType::Documentation => __DIR__ . '/../../stubs/documentation.md.stub', + NodeType::Group => __DIR__ . '/../../stubs/group.md.stub', + NodeType::Link => __DIR__ . '/../../stubs/link.md.stub', + }; } protected function qualifyClass($name): string @@ -102,6 +110,15 @@ public function handle(): bool ) : $knowledgeBasePanels->first(); + $this->nodeType = NodeType::from( + select( + label: 'What node type do you want to create?', + options: collect(NodeType::cases()) + ->mapWithKeys(fn (NodeType $type) => [$type->value => $type->name])->toArray(), + default: NodeType::Documentation->value, + ) + ); + $this->docsId = text( label: 'Enter the ID of the documentation page in dot-notation:', placeholder: 'Such as "users.introduction"', @@ -109,8 +126,10 @@ public function handle(): bool validate: ['name' => 'required|regex:/^[\w\-\.]+$/i'] ); - if (count(explode('.', $this->docsId)) > 3) { - error('You can nest documentations only 3 levels deep!'); + $maximumNestingLevel = $this->nodeType === NodeType::Group ? 1 : 3; + + if (count(explode('.', $this->docsId)) > $maximumNestingLevel) { + error("Maximum nesting level for type [{$this->nodeType->name}] is {$maximumNestingLevel}."); return false; } @@ -139,6 +158,10 @@ public function handle(): bool } } + if ($this->nodeType === NodeType::Group) { + info('A group needs one or more child items in order to appear in your knowledge base panel. Call this command again to create the items.'); + } + return true; } } diff --git a/stubs/documentation.md.stub b/stubs/documentation.md.stub new file mode 100644 index 0000000..bb5805b --- /dev/null +++ b/stubs/documentation.md.stub @@ -0,0 +1,4 @@ +--- +type: documentation +--- + diff --git a/stubs/group.md.stub b/stubs/group.md.stub new file mode 100644 index 0000000..5749321 --- /dev/null +++ b/stubs/group.md.stub @@ -0,0 +1,4 @@ +--- +type: group +--- + diff --git a/stubs/link.md.stub b/stubs/link.md.stub new file mode 100644 index 0000000..bf4faba --- /dev/null +++ b/stubs/link.md.stub @@ -0,0 +1,5 @@ +--- +type: link +url: "#" +--- + diff --git a/stubs/markdown.md.stub b/stubs/markdown.md.stub deleted file mode 100644 index 7390094..0000000 --- a/stubs/markdown.md.stub +++ /dev/null @@ -1,4 +0,0 @@ ---- - ---- - From 05794366674c58c4600488f871b5e3941407cd3e Mon Sep 17 00:00:00 2001 From: Lukas Frey Date: Sun, 7 Dec 2025 12:23:03 +0100 Subject: [PATCH 32/33] chore: merge Signed-off-by: Lukas Frey --- src/KnowledgeBase.php | 4 ++++ src/Models/FlatfileNode.php | 2 +- src/Support/FlatfileParser.php | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/KnowledgeBase.php b/src/KnowledgeBase.php index f0b2b42..502533a 100755 --- a/src/KnowledgeBase.php +++ b/src/KnowledgeBase.php @@ -119,6 +119,10 @@ public function documentable(Documentable | string $documentable, ?string $panel $panelId ??= static::panel()->getId(); + if (! Filament::getPanel($panelId)) { + throw new Exception('The provided panel does not exist.'); + } + if ($model = $this->model()::query()->find($panelId . '.' . $documentable)) { return $model; } diff --git a/src/Models/FlatfileNode.php b/src/Models/FlatfileNode.php index 056f8ba..219c9ff 100644 --- a/src/Models/FlatfileNode.php +++ b/src/Models/FlatfileNode.php @@ -36,7 +36,7 @@ class FlatfileNode extends Model implements Documentable 'title' => 'string', 'order' => 'integer', 'active' => 'boolean', - 'data' => 'string', + 'data' => 'json', 'parent_id' => 'string', 'panel_id' => 'string', ]; diff --git a/src/Support/FlatfileParser.php b/src/Support/FlatfileParser.php index 514b4be..2d1de9f 100644 --- a/src/Support/FlatfileParser.php +++ b/src/Support/FlatfileParser.php @@ -142,7 +142,7 @@ protected function parseGroupFile(SplFileInfo $file, string $id, Fluent $data, b protected function processDocumentationFile(SplFileInfo $file, string $id, Fluent $data, bool $checkParents = false): array { $result = [ - 'data' => serialize([ + 'data' => json_encode([ ...$this->getCustomData($data), 'content' => $data->get('html'), ]), From 0fe6ba987eb06deca071645ac5e1ed4630baece0 Mon Sep 17 00:00:00 2001 From: Lukas Frey Date: Sun, 7 Dec 2025 12:24:07 +0100 Subject: [PATCH 33/33] chore: pint Signed-off-by: Lukas Frey --- config/filament-knowledge-base.php | 2 +- src/Actions/Forms/Components/HelpAction.php | 8 +++--- src/Actions/HelpAction.php | 8 ++++-- src/Actions/Tables/Components/HelpAction.php | 8 +++--- src/Commands/MakeDocumentationCommand.php | 2 +- .../Resources/DocumentationResource.php | 28 +++++++++---------- src/Models/FlatfileNode.php | 3 +- src/Plugins/KnowledgeBaseCompanionPlugin.php | 2 +- src/Support/FlatfileParser.php | 3 +- 9 files changed, 34 insertions(+), 30 deletions(-) diff --git a/config/filament-knowledge-base.php b/config/filament-knowledge-base.php index 2ee8b90..13395cc 100644 --- a/config/filament-knowledge-base.php +++ b/config/filament-knowledge-base.php @@ -15,5 +15,5 @@ NodeType::Documentation->value => 'heroicon-o-document', NodeType::Link->value => 'heroicon-o-link', NodeType::Group->value => null, - ] + ], ]; diff --git a/src/Actions/Forms/Components/HelpAction.php b/src/Actions/Forms/Components/HelpAction.php index a33b91f..9c37be1 100644 --- a/src/Actions/Forms/Components/HelpAction.php +++ b/src/Actions/Forms/Components/HelpAction.php @@ -41,16 +41,16 @@ public static function forDocumentable(Documentable | string $documentable, ?str ->icon('heroicon-o-question-mark-circle') ->when( KnowledgeBase::companion()->hasModalPreviews(), - fn(HelpAction $action) => $action - ->modalContent(fn() => static::getContentView($documentable)) + fn (HelpAction $action) => $action + ->modalContent(fn () => static::getContentView($documentable)) ->modalHeading($documentable->getTitle()) ->modalSubmitAction(false) ->modalCancelActionLabel(__('filament-knowledge-base::translations.close')) ->when( KnowledgeBase::companion()->hasSlideOverPreviews(), - fn(HelpAction $action) => $action->slideOver() + fn (HelpAction $action) => $action->slideOver() ), - fn(HelpAction $action) => $action->url($documentable->getUrl()) + fn (HelpAction $action) => $action->url($documentable->getUrl()) ) ; } diff --git a/src/Actions/HelpAction.php b/src/Actions/HelpAction.php index 60eb65d..7e2b53e 100644 --- a/src/Actions/HelpAction.php +++ b/src/Actions/HelpAction.php @@ -27,27 +27,29 @@ public function generic(): HelpAction public static function forDocumentable(Documentable | string $documentable, ?string $panelId = null): HelpAction { $documentable = KnowledgeBase::documentable($documentable, $panelId); + return static::make("help.{$documentable->getId()}") ->label($documentable->getTitle()) ->icon($documentable->getIcon()) ->when( KnowledgeBase::companion()->hasModalPreviews(), - fn(HelpAction $action) => $action + fn (HelpAction $action) => $action ->modalHeading(function () use ($documentable) { return new HtmlString("

{$documentable->getTitle()}

"); }) ->modalContent(function () use ($documentable) { $content = data_get($documentable->getData(), 'content', ''); $body = new HtmlString("
{$content}
"); + return $body; }) ->modalCancelActionLabel(__('filament-knowledge-base::translations.close')) ->modalSubmitAction(false) ->when( KnowledgeBase::companion()->hasSlideOverPreviews(), - fn(HelpAction $action) => $action->slideOver() + fn (HelpAction $action) => $action->slideOver() ), - fn(HelpAction $action) => $action->url($documentable->getUrl()) + fn (HelpAction $action) => $action->url($documentable->getUrl()) ) ; } diff --git a/src/Actions/Tables/Components/HelpAction.php b/src/Actions/Tables/Components/HelpAction.php index 1de06ec..6718644 100644 --- a/src/Actions/Tables/Components/HelpAction.php +++ b/src/Actions/Tables/Components/HelpAction.php @@ -41,16 +41,16 @@ public static function forDocumentable(Documentable | string $documentable, ?str ->icon('heroicon-o-question-mark-circle') ->when( KnowledgeBase::companion()->hasModalPreviews(), - fn(HelpAction $action) => $action - ->modalContent(fn() => static::getContentView($documentable)) + fn (HelpAction $action) => $action + ->modalContent(fn () => static::getContentView($documentable)) ->modalHeading($documentable->getTitle()) ->modalSubmitAction(false) ->modalCancelActionLabel(__('filament-knowledge-base::translations.close')) ->when( KnowledgeBase::companion()->hasSlideOverPreviews(), - fn(HelpAction $action) => $action->slideOver() + fn (HelpAction $action) => $action->slideOver() ), - fn(HelpAction $action) => $action->url($documentable->getUrl()) + fn (HelpAction $action) => $action->url($documentable->getUrl()) ) ; } diff --git a/src/Commands/MakeDocumentationCommand.php b/src/Commands/MakeDocumentationCommand.php index 778cd85..a85db21 100644 --- a/src/Commands/MakeDocumentationCommand.php +++ b/src/Commands/MakeDocumentationCommand.php @@ -12,8 +12,8 @@ use Illuminate\Support\Facades\File; use Illuminate\Support\Stringable; -use function Laravel\Prompts\info; use function Laravel\Prompts\error; +use function Laravel\Prompts\info; use function Laravel\Prompts\select; use function Laravel\Prompts\text; diff --git a/src/Filament/Resources/DocumentationResource.php b/src/Filament/Resources/DocumentationResource.php index f6e92f2..f6b1c33 100644 --- a/src/Filament/Resources/DocumentationResource.php +++ b/src/Filament/Resources/DocumentationResource.php @@ -21,19 +21,19 @@ public static function getGloballySearchableAttributes(): array { return [ 'title', - 'data' + 'data', ]; } -// public static function modifyGlobalSearchQuery(Builder $query, string $search): void -// { -//// $query->orWhereRaw(" -//// json_extract(data, '$.content') LIKE '%$search%'; -//// "); -// $query->orWhereLike('data', "%$search%"); -// } + // public static function modifyGlobalSearchQuery(Builder $query, string $search): void + // { + // // $query->orWhereRaw(" + // // json_extract(data, '$.content') LIKE '%$search%'; + // // "); + // $query->orWhereLike('data', "%$search%"); + // } - protected static string|null|\BackedEnum $navigationIcon = 'heroicon-o-rectangle-stack'; + protected static string | null | \BackedEnum $navigationIcon = 'heroicon-o-rectangle-stack'; public static function getPages(): array { @@ -54,19 +54,19 @@ public static function getGlobalSearchResultUrl(Model $record): ?string return ViewDocumentation::getUrl(['record' => $record], panel: KnowledgeBase::panel()->getId()); } - public static function getGlobalSearchResultTitle(Model $record): string|Htmlable + public static function getGlobalSearchResultTitle(Model $record): string | Htmlable { return $record->title; -// return str($record->slug) -// ->replace('/', ' -> '); + // return str($record->slug) + // ->replace('/', ' -> '); } - public static function resolveRecordRouteBinding(int|string $key, ?\Closure $modifyQuery = null): ?Model + public static function resolveRecordRouteBinding(int | string $key, ?\Closure $modifyQuery = null): ?Model { // TODO: First try to load it from a standalone (App/Docs) class $record = parent::resolveRecordRouteBinding($key); - if (!$record?->isActive()) { + if (! $record?->isActive()) { return null; } diff --git a/src/Models/FlatfileNode.php b/src/Models/FlatfileNode.php index 219c9ff..9498f7c 100644 --- a/src/Models/FlatfileNode.php +++ b/src/Models/FlatfileNode.php @@ -196,7 +196,8 @@ public function toNavigationGroup(): NavigationGroup $canHaveIcon = $this ->children()->where(fn (FlatfileNode $child) => $child->children()->isNotEmpty()) - ->isEmpty(); + ->isEmpty() + ; return NavigationGroup::make($this->getTitle()) ->icon($canHaveIcon ? $this->getIcon() : null) diff --git a/src/Plugins/KnowledgeBaseCompanionPlugin.php b/src/Plugins/KnowledgeBaseCompanionPlugin.php index 40e639b..c72e12a 100644 --- a/src/Plugins/KnowledgeBaseCompanionPlugin.php +++ b/src/Plugins/KnowledgeBaseCompanionPlugin.php @@ -109,7 +109,7 @@ public function register(Panel $panel): void // 'icon' => 'heroicon-o-user', // 'slot' => new HtmlString('test'), // ]), -// fn (): string => $this->getKnowledgeBasePanelButton()->toHtml(), + // fn (): string => $this->getKnowledgeBasePanelButton()->toHtml(), ) ) // ->renderHook( diff --git a/src/Support/FlatfileParser.php b/src/Support/FlatfileParser.php index 2d1de9f..2be0f1c 100644 --- a/src/Support/FlatfileParser.php +++ b/src/Support/FlatfileParser.php @@ -192,7 +192,8 @@ protected function getCustomData(Fluent $data): array 'data', 'content', ]) - ->all(); + ->all() + ; } public function renderer(string $renderer): static