diff --git a/app/Http/Controllers/ShowDocumentationController.php b/app/Http/Controllers/ShowDocumentationController.php index 99166c45..cea666fb 100644 --- a/app/Http/Controllers/ShowDocumentationController.php +++ b/app/Http/Controllers/ShowDocumentationController.php @@ -46,6 +46,16 @@ public function __invoke(Request $request, string $platform, string $version, ?s fn () => $this->getPageProperties($platform, $version, $page) ); } catch (InvalidArgumentException $e) { + $resolvedPage = app(DocsVersionService::class)->resolvePageForVersion($platform, $version, $page); + + if ($resolvedPage !== $page && file_exists(resource_path("views/docs/{$platform}/{$version}/{$resolvedPage}.md"))) { + return redirect(route('docs.show', [ + 'platform' => $platform, + 'version' => $version, + 'page' => $resolvedPage, + ]), 301); + } + return $this->redirectToFirstNavigationPage($navigation, $page); } $title = $pageProperties['title'].' - NativePHP '.$platform.' v'.$version; diff --git a/app/Livewire/VersionSwitcher.php b/app/Livewire/VersionSwitcher.php index 3c70a2e7..ecba1916 100644 --- a/app/Livewire/VersionSwitcher.php +++ b/app/Livewire/VersionSwitcher.php @@ -2,6 +2,7 @@ namespace App\Livewire; +use App\Services\DocsVersionService; use Illuminate\View\ViewException; use Livewire\Attributes\Locked; use Livewire\Component; @@ -34,11 +35,25 @@ public function mount(array $versions) $this->platform = request()->route()->parameter('platform'); $this->version = request()->route()->parameter('version'); $this->page = request()->route()->parameter('page'); + + $prereleaseVersions = config("docs.prerelease_versions.{$this->platform}", []); + + foreach ($versions as $number => $label) { + if (in_array($number, $prereleaseVersions)) { + $versions[$number] = "{$label} (beta)"; + } + } + + krsort($versions); + $this->versions = $versions; } public function updatedVersion() { + $this->page = app(DocsVersionService::class) + ->resolvePageForVersion($this->platform, $this->version, $this->page); + if (! $this->pageExists($this->platform, $this->version, $this->page)) { $this->page = 'introduction'; } diff --git a/app/Services/DocsSearchService.php b/app/Services/DocsSearchService.php index 5c0c08ad..01b04e25 100644 --- a/app/Services/DocsSearchService.php +++ b/app/Services/DocsSearchService.php @@ -144,8 +144,8 @@ public function getLatestVersions(): array $versions = $this->getVersions(); return [ - 'desktop' => collect($versions['desktop'] ?? [])->sort()->last() ?? '2', - 'mobile' => collect($versions['mobile'] ?? [])->sort()->last() ?? '3', + 'desktop' => (string) (config('docs.latest_versions.desktop') ?? collect($versions['desktop'] ?? [])->sort()->last() ?? '2'), + 'mobile' => (string) (config('docs.latest_versions.mobile') ?? collect($versions['mobile'] ?? [])->sort()->last() ?? '3'), ]; } diff --git a/app/Services/DocsVersionService.php b/app/Services/DocsVersionService.php index 474ac8a1..1cd9902d 100644 --- a/app/Services/DocsVersionService.php +++ b/app/Services/DocsVersionService.php @@ -9,6 +9,7 @@ public function determineCanonicalUrl(string $platform, string $page): string $latestVersion = $platform === 'mobile' ? config('docs.latest_versions.mobile') : config('docs.latest_versions.desktop'); $page = $this->resolveOldVersionApisWithPluginsCorePage($platform, $latestVersion, $page); + $page = $this->resolvePageForVersion($platform, $latestVersion, $page); $latestPagePath = resource_path("views/docs/{$platform}/{$latestVersion}/{$page}.md"); @@ -21,6 +22,39 @@ public function determineCanonicalUrl(string $platform, string $page): string ]); } + /** + * Map a page to its equivalent path in the target version, following the + * configured renames in either direction. A page renamed in v4 resolves + * old-to-new when targeting v4 or later, and new-to-old when targeting + * anything earlier. + */ + public function resolvePageForVersion(string $platform, int|string $targetVersion, string $page): string + { + $renames = config("docs.renamed_pages.{$platform}", []); + + ksort($renames); + + foreach ($renames as $renamedInVersion => $map) { + if ((int) $targetVersion >= (int) $renamedInVersion && isset($map[$page])) { + $page = $map[$page]; + } + } + + krsort($renames); + + foreach ($renames as $renamedInVersion => $map) { + if ((int) $targetVersion < (int) $renamedInVersion) { + $reversed = array_flip($map); + + if (isset($reversed[$page])) { + $page = $reversed[$page]; + } + } + } + + return $page; + } + /** * Handle renamed paths (e.g., apis/* moved to plugins/core/*) */ diff --git a/config/docs.php b/config/docs.php index c459a5cd..be584a09 100644 --- a/config/docs.php +++ b/config/docs.php @@ -7,9 +7,10 @@ | Documentation Latest Versions |-------------------------------------------------------------------------- | - | This configuration defines the latest version for each documentation - | platform. When a user views an older version, they will see a notice - | prompting them to view the latest version. + | This configuration defines the latest stable version for each + | documentation platform. When a user views an older version, they will + | see a notice prompting them to view the latest version. Unversioned + | docs URLs redirect here. | */ @@ -18,4 +19,41 @@ 'mobile' => 3, ], + /* + |-------------------------------------------------------------------------- + | Documentation Pre-release Versions + |-------------------------------------------------------------------------- + | + | Versions listed here are published but still in beta. They are labelled + | as beta in the version switcher, display a pre-release notice on every + | page, and are never the default version users are redirected to. + | + */ + + 'prerelease_versions' => [ + 'desktop' => [], + 'mobile' => [4], + ], + + /* + |-------------------------------------------------------------------------- + | Renamed Documentation Pages + |-------------------------------------------------------------------------- + | + | Pages that were renamed in a given version, keyed by the version the + | rename happened in, mapping the old path to the new path. Used to map + | a page to its equivalent when moving between versions (in both + | directions) and to redirect stale URLs within a version. + | + */ + + 'renamed_pages' => [ + 'desktop' => [], + 'mobile' => [ + 4 => [ + 'the-basics/native-components' => 'the-basics/native-ui', + ], + ], + ], + ]; diff --git a/resources/views/components/docs/beta-version-notice.blade.php b/resources/views/components/docs/beta-version-notice.blade.php new file mode 100644 index 00000000..46be3554 --- /dev/null +++ b/resources/views/components/docs/beta-version-notice.blade.php @@ -0,0 +1,51 @@ +@props(['platform', 'version', 'page']) + +@php + $isPrerelease = in_array((int) $version, config("docs.prerelease_versions.{$platform}", [])); + + if ($isPrerelease) { + $stableVersion = config("docs.latest_versions.{$platform}"); + $page = app(\App\Services\DocsVersionService::class)->resolvePageForVersion($platform, $stableVersion, $page); + $stablePagePath = resource_path("views/docs/{$platform}/{$stableVersion}/{$page}.md"); + $targetPage = file_exists($stablePagePath) ? $page : 'getting-started/introduction'; + + $stableUrl = route('docs.show', [ + 'platform' => $platform, + 'version' => $stableVersion, + 'page' => $targetPage, + ]); + } +@endphp + +@if ($isPrerelease) +
+ +
+

You're viewing pre-release documentation — version {{ $version }}.x is in beta

+

+ Features, APIs and behaviour may change before the stable release. + + View the stable version ({{ $stableVersion }}.x) + +

+
+
+@endif diff --git a/resources/views/components/docs/old-version-notice.blade.php b/resources/views/components/docs/old-version-notice.blade.php index 818f164f..cfb6df41 100644 --- a/resources/views/components/docs/old-version-notice.blade.php +++ b/resources/views/components/docs/old-version-notice.blade.php @@ -5,6 +5,7 @@ $isOldVersion = $latestVersion && (int) $version < (int) $latestVersion; if ($isOldVersion) { + $page = app(\App\Services\DocsVersionService::class)->resolvePageForVersion($platform, $latestVersion, $page); $latestPagePath = resource_path("views/docs/{$platform}/{$latestVersion}/{$page}.md"); // Handle renamed paths (e.g., apis/* moved to plugins/core/*) diff --git a/resources/views/components/plugin-toc.blade.php b/resources/views/components/plugin-toc.blade.php index c156267e..5edbf7fc 100644 --- a/resources/views/components/plugin-toc.blade.php +++ b/resources/views/components/plugin-toc.blade.php @@ -39,13 +39,13 @@ -