diff --git a/packages/framework/resources/views/layouts/head.blade.php b/packages/framework/resources/views/layouts/head.blade.php index 529d6ca99fb..15170d3951f 100644 --- a/packages/framework/resources/views/layouts/head.blade.php +++ b/packages/framework/resources/views/layouts/head.blade.php @@ -3,7 +3,7 @@ {{ isset($title) ? config('hyde.name', 'HydePHP') . ' - ' . $title : config('hyde.name', 'HydePHP') }} @if (file_exists(Hyde::path('_media/favicon.ico'))) - + @endif {{-- App Meta Tags --}} diff --git a/packages/framework/resources/views/layouts/scripts.blade.php b/packages/framework/resources/views/layouts/scripts.blade.php index d44c50bb184..5a39809bf75 100644 --- a/packages/framework/resources/views/layouts/scripts.blade.php +++ b/packages/framework/resources/views/layouts/scripts.blade.php @@ -2,12 +2,12 @@ @unless(Asset::hasMediaFile('hyde.js')) @else - + @endunless {{-- The compiled Laravel Mix scripts --}} @if(Asset::hasMediaFile('app.js')) - + @endif {{-- Add any extra scripts to include before the closing tag --}} diff --git a/packages/framework/resources/views/layouts/styles.blade.php b/packages/framework/resources/views/layouts/styles.blade.php index 73fe93a3eb2..a33133bdaba 100644 --- a/packages/framework/resources/views/layouts/styles.blade.php +++ b/packages/framework/resources/views/layouts/styles.blade.php @@ -2,12 +2,12 @@ @unless(Asset::hasMediaFile('hyde.css')) @else - + @endunless {{-- The compiled Tailwind/App styles --}} @if(Asset::hasMediaFile('app.css')) - + @endif {{-- Add any extra styles to include after the others --}} diff --git a/packages/framework/src/Concerns/Internal/FileHelpers.php b/packages/framework/src/Concerns/Internal/FileHelpers.php index cebaf87417c..34be1f7c5f0 100644 --- a/packages/framework/src/Concerns/Internal/FileHelpers.php +++ b/packages/framework/src/Concerns/Internal/FileHelpers.php @@ -2,7 +2,9 @@ namespace Hyde\Framework\Concerns\Internal; +use Hyde\Framework\Contracts\RouteContract; use Hyde\Framework\Models\Pages\DocumentationPage; +use Illuminate\Support\Facades\View; /** * Offloads file helper methods for the Hyde Facade. @@ -73,14 +75,24 @@ public static function pageLink(string $destination): string /** * Inject the proper number of `../` before the links in Blade templates. * - * @see \Hyde\Framework\Testing\Unit\FileHelperRelativeLinkTest + * Since v0.50.x you no longer have to supply a current page as it will be automatically retrieved from the View. * * @param string $destination relative to output directory on compiled site - * @param string $current the current URI path relative to the site root + * @param string|null $current the current URI path relative to the site root * @return string + * + * @see \Hyde\Framework\Testing\Unit\FileHelperRelativeLinkTest */ - public static function relativeLink(string $destination, string $current = ''): string + public static function relativeLink(string $destination, ?string $current = null): string { + if (str_starts_with($destination, '../')) { + return $destination; + } + + if ($current === null) { + $current = static::currentPage(); + } + $nestCount = substr_count($current, '/'); $route = ''; if ($nestCount > 0) { @@ -91,11 +103,32 @@ public static function relativeLink(string $destination, string $current = ''): return str_replace('//', '/', $route); } + /** + * Get the current page path, or fall back to the root path. + */ + public static function currentPage(): string + { + return View::shared('currentPage', ''); + } + + /** + * Get the current page route, or fall back to null. + */ + public static function currentRoute(): ?RouteContract + { + return View::shared('currentRoute'); + } + /** * Gets a relative web link to the given image stored in the _site/media folder. + * Since v0.50.x you no longer have to supply a current page as it will be automatically retrieved from the View. */ - public static function image(string $name, string $current = ''): string + public static function image(string $name, string $current = null): string { + if ($current === null) { + $current = static::currentPage(); + } + if (str_starts_with($name, 'http')) { return $name; } diff --git a/packages/framework/src/Contracts/RouteContract.php b/packages/framework/src/Contracts/RouteContract.php index 0091d8cb329..2bcceb29c73 100644 --- a/packages/framework/src/Contracts/RouteContract.php +++ b/packages/framework/src/Contracts/RouteContract.php @@ -57,13 +57,13 @@ public function getOutputFilePath(): string; /** * Resolve a site web link to the file, using pretty URLs if enabled. * - * @param string $currentPage The current page path, or blank to get use the site root as base. * @return string Relative path to the page */ - public function getLink(string $currentPage = ''): string; + public function getLink(): string; /** * Cast a route object into a string that can be used in a href attribute. + * Should be the same as getLink(). */ public function __toString(): string; } diff --git a/packages/framework/src/Contracts/RouteFacadeContract.php b/packages/framework/src/Contracts/RouteFacadeContract.php index a9082743aae..1566253dc99 100644 --- a/packages/framework/src/Contracts/RouteFacadeContract.php +++ b/packages/framework/src/Contracts/RouteFacadeContract.php @@ -59,4 +59,9 @@ public static function getFromModel(PageContract $page): RouteContract; * @return \Illuminate\Support\Collection<\Hyde\Framework\Contracts\RouteContract> */ public static function all(): Collection; + + /** + * Get the current route for the page being rendered. + */ + public static function current(): RouteContract; } diff --git a/packages/framework/src/Facades/Route.php b/packages/framework/src/Facades/Route.php index bde8e17b5e2..0f1aa329ecc 100644 --- a/packages/framework/src/Facades/Route.php +++ b/packages/framework/src/Facades/Route.php @@ -42,4 +42,10 @@ public static function all(): Collection { return RouteModel::all(); } + + /** @inheritDoc */ + public static function current(): RouteModel + { + return RouteModel::current(); + } } diff --git a/packages/framework/src/Models/NavItem.php b/packages/framework/src/Models/NavItem.php index 0e2416814c3..ff1822b729c 100644 --- a/packages/framework/src/Models/NavItem.php +++ b/packages/framework/src/Models/NavItem.php @@ -72,15 +72,15 @@ public static function toRoute(RouteContract $route, string $title, int $priorit /** * Resolve a link to the navigation item. - * - * @param string $currentPage - * @return string */ - public function resolveLink(string $currentPage = ''): string + public function resolveLink(): string { - return $this->href ?? $this->route->getLink($currentPage); + return $this->href ?? $this->route->getLink(); } + /** + * Resolve a link to the navigation item. + */ public function __toString(): string { return $this->resolveLink(); diff --git a/packages/framework/src/Models/NavigationMenu.php b/packages/framework/src/Models/NavigationMenu.php index 9bfeb82e50d..5db0bb0e817 100644 --- a/packages/framework/src/Models/NavigationMenu.php +++ b/packages/framework/src/Models/NavigationMenu.php @@ -68,8 +68,8 @@ public function sort(): self } /** @internal */ - public function getHomeLink(string $currentPage): string + public function getHomeLink(): string { - return Route::get('index')->getLink($currentPage); + return Route::get('index'); } } diff --git a/packages/framework/src/Models/Route.php b/packages/framework/src/Models/Route.php index a56db00f8ed..f08c8b0f0ca 100644 --- a/packages/framework/src/Models/Route.php +++ b/packages/framework/src/Models/Route.php @@ -67,9 +67,9 @@ public function getOutputFilePath(): string } /** @inheritDoc */ - public function getLink(string $currentPage = ''): string + public function getLink(): string { - return Hyde::relativeLink($this->getOutputFilePath(), $currentPage); + return Hyde::relativeLink($this->getOutputFilePath()); } /** @inheritDoc */ @@ -114,4 +114,10 @@ public static function all(): Collection { return Router::getInstance()->getRoutes(); } + + /** @inheritDoc */ + public static function current(): static + { + return Hyde::currentRoute() ?? throw new RouteNotFoundException('current'); + } } diff --git a/packages/framework/src/StaticPageBuilder.php b/packages/framework/src/StaticPageBuilder.php index 798a1ce03eb..760a59d0d56 100644 --- a/packages/framework/src/StaticPageBuilder.php +++ b/packages/framework/src/StaticPageBuilder.php @@ -41,6 +41,7 @@ public function __invoke() { view()->share('page', $this->page); view()->share('currentPage', $this->page->getCurrentPagePath()); + view()->share('currentRoute', $this->page->getRoute()); $this->needsDirectory(static::$outputPath); $this->needsDirectory(Hyde::getSiteOutputPath($this->page::getOutputDirectory())); diff --git a/packages/framework/tests/Feature/RouteFacadeTest.php b/packages/framework/tests/Feature/RouteFacadeTest.php index 71fd2fd02c1..47cc5b3bf1a 100644 --- a/packages/framework/tests/Feature/RouteFacadeTest.php +++ b/packages/framework/tests/Feature/RouteFacadeTest.php @@ -41,4 +41,10 @@ public function test_route_facade_all_method_calls_all_method() { $this->assertEquals(BaseRoute::all(), Route::all()); } + + public function test_route_facade_current_method_calls_current_method() + { + $this->mockRoute(); + $this->assertEquals(BaseRoute::current(), Route::current()); + } } diff --git a/packages/framework/tests/Feature/RouteTest.php b/packages/framework/tests/Feature/RouteTest.php index 165f069ca07..b8982e71b4e 100644 --- a/packages/framework/tests/Feature/RouteTest.php +++ b/packages/framework/tests/Feature/RouteTest.php @@ -135,7 +135,6 @@ public function test_route_facade_all_method_returns_all_routes() $this->assertEquals(Router::getInstance()->getRoutes(), Route::all()); } - // test getLink uses hyde::relativeLink() to get the correct path for root pages public function test_get_link_returns_correct_path_for_root_pages() { $route = new Route(new MarkdownPage(slug: 'foo')); @@ -143,7 +142,6 @@ public function test_get_link_returns_correct_path_for_root_pages() $this->assertEquals('foo.html', $route->getLink()); } - // test getLink uses hyde::relativeLink() to get the correct path for nested pages public function test_get_link_returns_correct_path_for_nested_pages() { $route = new Route(new MarkdownPage(slug: 'foo/bar')); @@ -154,11 +152,11 @@ public function test_get_link_returns_correct_path_for_nested_pages() public function test_get_link_returns_correct_path_for_nested_current_page() { $route = new Route(new MarkdownPage(slug: 'foo')); - $this->assertEquals(Hyde::relativeLink($route->getOutputFilePath(), 'foo/bar'), $route->getLink('foo/bar')); - $this->assertEquals('../foo.html', $route->getLink('foo/bar')); + view()->share('currentPage', 'foo/bar'); + $this->assertEquals(Hyde::relativeLink($route->getOutputFilePath(), 'foo/bar'), $route->getLink()); + $this->assertEquals('../foo.html', $route->getLink()); } - // test getLink returns pretty url if enabled public function test_get_link_returns_pretty_url_if_enabled() { config(['hyde.pretty_urls' => true]); @@ -167,10 +165,22 @@ public function test_get_link_returns_pretty_url_if_enabled() $this->assertEquals('foo', $route->getLink()); } - // test to string is alias for getLink public function test_to_string_is_alias_for_get_link() { $route = new Route(new MarkdownPage(slug: 'foo')); $this->assertEquals($route->getLink(), (string) $route); } + + public function test_current_returns_current_route() + { + $route = new Route(new MarkdownPage(slug: 'foo')); + view()->share('currentRoute', $route); + $this->assertEquals($route, Route::current()); + } + + public function test_current_throws_exception_if_route_is_not_found() + { + $this->expectException(RouteNotFoundException::class); + Route::current(); + } } diff --git a/packages/framework/tests/Unit/FileHelperRelativeLinkTest.php b/packages/framework/tests/Unit/FileHelperRelativeLinkTest.php index a8770cb2095..36039cff439 100644 --- a/packages/framework/tests/Unit/FileHelperRelativeLinkTest.php +++ b/packages/framework/tests/Unit/FileHelperRelativeLinkTest.php @@ -97,4 +97,9 @@ public function test_helper_rewrites_documentation_page_index_when_using_pretty_ $this->assertEquals('../docs/', Hyde::relativeLink('docs/index.html', 'foo/bar.html')); $this->assertEquals('../docs/', Hyde::relativeLink('docs/index.html', 'docs/foo.html')); } + + public function test_helper_does_not_rewrite_already_processed_links() + { + $this->assertEquals('../foo', Hyde::relativeLink('../foo', 'foo/bar.html')); + } } diff --git a/packages/framework/tests/Unit/HydeFileHelpersTest.php b/packages/framework/tests/Unit/HydeFileHelpersTest.php new file mode 100644 index 00000000000..71afd861ab2 --- /dev/null +++ b/packages/framework/tests/Unit/HydeFileHelpersTest.php @@ -0,0 +1,35 @@ +share('currentPage', 'foo'); + $this->assertEquals('foo', Hyde::currentPage()); + } + + public function test_current_page_falls_back_to_empty_string_if_current_page_view_property_is_not_set() + { + $this->assertEquals('', Hyde::currentPage()); + } + + public function test_current_route_returns_current_route_view_property() + { + view()->share('currentRoute', Route::get('index')); + $this->assertEquals(Route::get('index'), Hyde::currentRoute()); + } + + public function test_current_route_falls_back_to_null_if_current_route_view_property_is_not_set() + { + $this->assertNull(Hyde::currentRoute()); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php index ed7de403dc1..217e323523a 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -3,6 +3,8 @@ namespace Hyde\Testing; use Hyde\Framework\Hyde; +use Hyde\Framework\Models\Pages\MarkdownPage; +use Hyde\Framework\Models\Route; use LaravelZero\Framework\Testing\TestCase as BaseTestCase; abstract class TestCase extends BaseTestCase @@ -57,4 +59,9 @@ protected function tearDown(): void { parent::tearDown(); } + + protected function mockRoute() + { + view()->share('currentRoute', (new Route(new MarkdownPage()))); + } }