diff --git a/packages/framework/src/Concerns/FacadeHelpers/HydeSmartDocsFacade.php b/packages/framework/src/Concerns/FacadeHelpers/HydeSmartDocsFacade.php deleted file mode 100644 index 932ba292faa..00000000000 --- a/packages/framework/src/Concerns/FacadeHelpers/HydeSmartDocsFacade.php +++ /dev/null @@ -1,51 +0,0 @@ -process(); - } - - /** - * Does the current document use Torchlight? - * - * @return bool - */ - public function hasTorchlight(): bool - { - return Features::hasTorchlight() && str_contains($this->html, 'Syntax highlighted by torchlight.dev'); - } - - /** - * Do we satisfy the requirements to render an edit source button in the supplied position? - * - * @param string $inPosition - * @return bool - */ - protected function canRenderSourceLink(string $inPosition): bool - { - $config = config('docs.edit_source_link_position', 'both'); - $positions = $config === 'both' ? ['header', 'footer'] : [$config]; - - return ($this->page->getOnlineSourcePath() !== false) && in_array($inPosition, $positions); - } -} diff --git a/packages/framework/src/Concerns/JsonSerializesArrayable.php b/packages/framework/src/Concerns/JsonSerializesArrayable.php index 1f3a6178bf0..97e42cc58b1 100644 --- a/packages/framework/src/Concerns/JsonSerializesArrayable.php +++ b/packages/framework/src/Concerns/JsonSerializesArrayable.php @@ -2,6 +2,13 @@ namespace Hyde\Framework\Concerns; +/** + * Automatically serializes an Arrayable interface when JSON is requested. + * + * @see \JsonSerializable + * @see \Illuminate\Contracts\Support\Arrayable + * @see \Hyde\Framework\Testing\Unit\JsonSerializesArrayableTest + */ trait JsonSerializesArrayable { /** @inheritDoc */ @@ -9,4 +16,7 @@ public function jsonSerialize() { return $this->toArray(); } + + /** @inheritDoc */ + abstract public function toArray(); } diff --git a/packages/framework/src/Contracts/HydeKernelContract.php b/packages/framework/src/Contracts/HydeKernelContract.php index 4175d4aa80a..43cb068bf2a 100644 --- a/packages/framework/src/Contracts/HydeKernelContract.php +++ b/packages/framework/src/Contracts/HydeKernelContract.php @@ -8,8 +8,8 @@ * * @see \Hyde\Framework\HydeKernel * - * It is bound into the Laravel Application Service Container, - * and can be accessed in a few ways. + * It is stored as a singleton in the HydeKernel class, and is bound into the + * Laravel Application Service Container, and can be accessed in a few ways. * * - Commonly, you'll use the Hyde facade: * @see \Hyde\Framework\Hyde (previosly this namespace contained the actual Kernel) @@ -27,6 +27,12 @@ */ interface HydeKernelContract { + public function boot(): void; + + public static function setInstance(HydeKernelContract $instance): void; + + public static function getInstance(): HydeKernelContract; + public function getBasePath(): string; public function setBasePath(string $basePath); diff --git a/packages/framework/src/Contracts/RouteFacadeContract.php b/packages/framework/src/Contracts/RouteFacadeContract.php index 4fd9a13f11d..ad5797a4e52 100644 --- a/packages/framework/src/Contracts/RouteFacadeContract.php +++ b/packages/framework/src/Contracts/RouteFacadeContract.php @@ -69,4 +69,12 @@ public static function current(): RouteContract; * Get the home route, usually the index page route. */ public static function home(): RouteContract; + + /** + * Determine if the supplied route key exists in the route index. + * + * @param string $routeKey + * @return bool + */ + public static function exists(string $routeKey): bool; } diff --git a/packages/framework/src/Hyde.php b/packages/framework/src/Hyde.php index 6821e7c9aab..fc4b2bdcaf6 100644 --- a/packages/framework/src/Hyde.php +++ b/packages/framework/src/Hyde.php @@ -48,12 +48,6 @@ */ class Hyde extends Facade { - /** @psalm-return HydeKernel::class */ - protected static function getFacadeAccessor(): string - { - return HydeKernel::class; - } - public static function version(): string { return HydeKernel::version(); diff --git a/packages/framework/src/Models/Route.php b/packages/framework/src/Models/Route.php index 8632c7fe758..b116efc128f 100644 --- a/packages/framework/src/Models/Route.php +++ b/packages/framework/src/Models/Route.php @@ -40,6 +40,12 @@ public function __construct(PageContract $sourceModel) $this->routeKey = $this->constructRouteKey(); } + /** @inheritDoc */ + public function __toString(): string + { + return $this->getLink(); + } + /** @inheritDoc */ public function toArray() { @@ -50,6 +56,12 @@ public function toArray() ]; } + /** @inheritDoc */ + public function getLink(): string + { + return Hyde::relativeLink($this->getOutputFilePath()); + } + /** @inheritDoc */ public function getPageType(): string { @@ -86,18 +98,6 @@ public function getQualifiedUrl(): string return Hyde::url($this->getOutputFilePath()); } - /** @inheritDoc */ - public function getLink(): string - { - return Hyde::relativeLink($this->getOutputFilePath()); - } - - /** @inheritDoc */ - public function __toString(): string - { - return $this->getLink(); - } - /** @deprecated Use the route key property */ protected function constructRouteKey(): string { @@ -148,7 +148,7 @@ public static function home(): RouteContract return static::getFromKey('index'); } - /** @todo add to contract */ + /** @inheritDoc */ public static function exists(string $routeKey): bool { return RoutingService::getInstance()->getRoutes()->has($routeKey); diff --git a/packages/framework/src/Services/HydeSmartDocs.php b/packages/framework/src/Services/HydeSmartDocs.php index aee3d372ded..8af0455a729 100644 --- a/packages/framework/src/Services/HydeSmartDocs.php +++ b/packages/framework/src/Services/HydeSmartDocs.php @@ -2,7 +2,7 @@ namespace Hyde\Framework\Services; -use Hyde\Framework\Concerns\FacadeHelpers\HydeSmartDocsFacade; +use Hyde\Framework\Helpers\Features; use Hyde\Framework\Models\Pages\DocumentationPage; use Illuminate\Support\Str; @@ -16,8 +16,6 @@ */ class HydeSmartDocs { - use HydeSmartDocsFacade; - protected DocumentationPage $page; protected string $html; @@ -112,4 +110,40 @@ protected function renderSourceLink(): string config('docs.edit_source_link_text', 'Edit page') ); } + + /** + * Create a new HydeSmartDocs instance, process, and return it. + * + * @param \Hyde\Framework\Models\Pages\DocumentationPage $page The source page object + * @param string $html compiled HTML content + * @return static new processed instance + */ + public static function create(DocumentationPage $page, string $html): static + { + return (new self($page, $html))->process(); + } + + /** + * Does the current document use Torchlight? + * + * @return bool + */ + public function hasTorchlight(): bool + { + return Features::hasTorchlight() && str_contains($this->html, 'Syntax highlighted by torchlight.dev'); + } + + /** + * Do we satisfy the requirements to render an edit source button in the supplied position? + * + * @param string $inPosition + * @return bool + */ + protected function canRenderSourceLink(string $inPosition): bool + { + $config = config('docs.edit_source_link_position', 'both'); + $positions = $config === 'both' ? ['header', 'footer'] : [$config]; + + return ($this->page->getOnlineSourcePath() !== false) && in_array($inPosition, $positions); + } } diff --git a/packages/framework/src/Services/RoutingService.php b/packages/framework/src/Services/RoutingService.php index cc86267fc99..f2f0796b06f 100644 --- a/packages/framework/src/Services/RoutingService.php +++ b/packages/framework/src/Services/RoutingService.php @@ -19,8 +19,8 @@ * The routes defined can then also be used to power the RealtimeCompiler without * having to reverse-engineer the source file mapping. * - * Routes cannot be added manually, instead the route index is created using the - * exact same rules as the current autodiscovery process and compiled file output. + * Routes are not intended to be added manually, instead the route index is created using + * the exact same rules as the current autodiscovery process and compiled file output. * * The route index serves as a multidimensional mapping allowing you to * determine where a source file will be compiled to, and where a compiled diff --git a/packages/framework/tests/Feature/ConfigurableFeaturesTest.php b/packages/framework/tests/Feature/ConfigurableFeaturesTest.php index 77293830b68..0c0bda99f68 100644 --- a/packages/framework/tests/Feature/ConfigurableFeaturesTest.php +++ b/packages/framework/tests/Feature/ConfigurableFeaturesTest.php @@ -57,4 +57,16 @@ public function test_can_generate_sitemap_helper_returns_false_if_sitemaps_are_d config(['site.generate_sitemap' => false]); $this->assertFalse(Features::sitemap()); } + + public function test_to_array_method_returns_method_array() + { + $array = (new Features)->toArray(); + $this->assertIsArray($array); + $this->assertNotEmpty($array); + foreach ($array as $feature => $enabled) { + $this->assertIsString($feature); + $this->assertIsBool($enabled); + $this->assertStringStartsNotWith('has', $feature); + } + } } diff --git a/packages/framework/tests/Feature/DataCollectionTest.php b/packages/framework/tests/Feature/DataCollectionTest.php index c6cb2a8cc9e..d76f325a899 100644 --- a/packages/framework/tests/Feature/DataCollectionTest.php +++ b/packages/framework/tests/Feature/DataCollectionTest.php @@ -113,7 +113,6 @@ public function test_get_markdown_files_method_does_not_include_files_with_exten File::deleteDirectory(Hyde::path('_data/foo')); } - // test get markdown files method does not remove files starting with an underscore public function test_get_markdown_files_method_does_not_remove_files_starting_with_an_underscore() { mkdir(Hyde::path('_data/foo')); diff --git a/packages/framework/tests/Feature/HydeKernelTest.php b/packages/framework/tests/Feature/HydeKernelTest.php index 9350a91bf82..f628361f9f6 100644 --- a/packages/framework/tests/Feature/HydeKernelTest.php +++ b/packages/framework/tests/Feature/HydeKernelTest.php @@ -197,4 +197,29 @@ public function test_path_to_relative_helper_returns_relative_path_for_given_pat { $this->assertEquals('foo', Hyde::pathToRelative(Hyde::path('foo'))); } + + public function test_to_array_method() + { + $array = Hyde::toArray(); + + $this->assertTrue(is_array($array)); + $this->assertCount(4, $array); + + $this->assertArrayHasKey('basePath', $array); + $this->assertArrayHasKey('features', $array); + $this->assertArrayHasKey('pages', $array); + $this->assertArrayHasKey('routes', $array); + + $this->assertEquals(Hyde::getBasePath(), $array['basePath']); + $this->assertEquals(Hyde::features(), $array['features']); + $this->assertEquals(Hyde::pages(), $array['pages']); + $this->assertEquals(Hyde::routes(), $array['routes']); + + $this->assertEquals([ + 'basePath' => Hyde::getBasePath(), + 'features' => Hyde::features(), + 'pages' => Hyde::pages(), + 'routes' => Hyde::routes(), + ], Hyde::toArray()); + } } diff --git a/packages/framework/tests/Feature/MarkdownServiceTest.php b/packages/framework/tests/Feature/MarkdownServiceTest.php index b30ac3896ed..918fc308011 100644 --- a/packages/framework/tests/Feature/MarkdownServiceTest.php +++ b/packages/framework/tests/Feature/MarkdownServiceTest.php @@ -80,7 +80,6 @@ public function test_bladedown_can_be_enabled() $this->assertEquals("Hello World!\n", $service->parse()); } - // test raw html tags are stripped by default public function test_raw_html_tags_are_stripped_by_default() { $markdown = '
foo
'; @@ -89,7 +88,6 @@ public function test_raw_html_tags_are_stripped_by_default() $this->assertEquals("foo
<style>bar</style><script>hat</script>\n", $html); } - // test raw html tags are not stripped when explicitly enabled public function test_raw_html_tags_are_not_stripped_when_explicitly_enabled() { config(['markdown.allow_html' =>true]); diff --git a/packages/framework/tests/Feature/RouteTest.php b/packages/framework/tests/Feature/RouteTest.php index 0684b609655..c728638a426 100644 --- a/packages/framework/tests/Feature/RouteTest.php +++ b/packages/framework/tests/Feature/RouteTest.php @@ -216,4 +216,13 @@ public function test_home_helper_returns_index_route() { $this->assertEquals(Route::get('index'), Route::home()); } + + public function test_to_array_method() + { + $this->assertEquals([ + 'routeKey' => 'foo', + 'sourceModelPath' => '_pages/foo.md', + 'sourceModelType' => MarkdownPage::class, + ], (new MarkdownPage('foo'))->getRoute()->toArray()); + } } diff --git a/packages/framework/tests/Feature/Services/HydeSmartDocsTest.php b/packages/framework/tests/Feature/Services/HydeSmartDocsTest.php index beafa7ae23e..05559a33120 100644 --- a/packages/framework/tests/Feature/Services/HydeSmartDocsTest.php +++ b/packages/framework/tests/Feature/Services/HydeSmartDocsTest.php @@ -10,7 +10,6 @@ /** * @covers \Hyde\Framework\Services\HydeSmartDocs - * @covers \Hyde\Framework\Concerns\FacadeHelpers\HydeSmartDocsFacade */ class HydeSmartDocsTest extends TestCase { diff --git a/packages/framework/tests/Unit/Foundation/HyperlinksUrlPathHelpersTest.php b/packages/framework/tests/Unit/Foundation/HyperlinksUrlPathHelpersTest.php index 3e02e676c70..abb19308e3b 100644 --- a/packages/framework/tests/Unit/Foundation/HyperlinksUrlPathHelpersTest.php +++ b/packages/framework/tests/Unit/Foundation/HyperlinksUrlPathHelpersTest.php @@ -35,35 +35,30 @@ public function test_has_site_url_returns_true_when_site_url_is_set() $this->assertTrue($this->class->hasSiteUrl()); } - // test that url returns the site url when no path is given public function test_qualified_url_returns_site_url_when_no_path_is_given() { config(['site.url' => 'https://example.com']); $this->assertEquals('https://example.com', $this->class->url()); } - // test that url returns the site url plus the given path public function test_qualified_url_returns_site_url_plus_given_path() { config(['site.url' => 'https://example.com']); $this->assertEquals('https://example.com/path', $this->class->url('path')); } - // test that url returns the site url plus the given path with extension public function test_qualified_url_returns_site_url_plus_given_path_with_extension() { config(['site.url' => 'https://example.com']); $this->assertEquals('https://example.com/path.html', $this->class->url('path.html')); } - // test that url returns the site url plus the given path with extension and query string public function test_qualified_url_returns_site_url_plus_given_path_with_extension_and_query_string() { config(['site.url' => 'https://example.com']); $this->assertEquals('https://example.com/path.html?query=string', $this->class->url('path.html?query=string')); } - // test that url trims trailing slashes public function test_qualified_url_trims_trailing_slashes() { config(['site.url' => 'https://example.com/']); @@ -72,14 +67,12 @@ public function test_qualified_url_trims_trailing_slashes() $this->assertEquals('https://example.com/foo', $this->class->url('/foo/')); } - // test that url accepts multiple schemes public function test_qualified_url_accepts_multiple_schemes() { config(['site.url' => 'http://example.com']); $this->assertEquals('http://example.com', $this->class->url()); } - // test that url throws an exception when no site url is set public function test_qualified_url_throws_exception_when_no_site_url_is_set() { config(['site.url' => null]); @@ -88,14 +81,12 @@ public function test_qualified_url_throws_exception_when_no_site_url_is_set() $this->class->url(); } - // test that url uses default parameter when supplied and no site url is set public function test_qualified_url_uses_default_parameter_when_no_site_url_is_set() { config(['site.url' => null]); $this->assertEquals('bar/foo', $this->class->url('foo', 'bar')); } - // test that url does not use default parameter when supplied and a site url is set public function test_qualified_url_does_not_use_default_parameter_when_site_url_is_set() { config(['site.url' => 'https://example.com']); @@ -108,7 +99,6 @@ public function test_helper_returns_expected_string_when_site_url_is_set() $this->assertEquals('https://example.com/foo/bar.html', $this->class->url('foo/bar.html')); } - // test returned url uses pretty urls when enabled public function test_helper_returns_expected_string_when_pretty_urls_are_enabled() { config(['site.url' => 'https://example.com', 'site.pretty_urls' => true]); diff --git a/packages/framework/tests/Unit/JsonSerializesArrayableTest.php b/packages/framework/tests/Unit/JsonSerializesArrayableTest.php new file mode 100644 index 00000000000..b85b8308623 --- /dev/null +++ b/packages/framework/tests/Unit/JsonSerializesArrayableTest.php @@ -0,0 +1,35 @@ + 'bar']; + } + }; + + $this->assertEquals([ + 'foo' => 'bar', + ], $class->toArray()); + + $this->assertEquals([ + 'foo' => 'bar', + ], $class->jsonSerialize()); + + $this->assertEquals('{"foo":"bar"}', json_encode($class)); + } +}