From 45d07ac39364801b69e88934c56dbd4c80cdb442 Mon Sep 17 00:00:00 2001 From: Josh Bruce Date: Thu, 28 Oct 2021 09:07:42 -0500 Subject: [PATCH 01/10] use strict types everywhere --- public/index.php | 2 ++ src/PageComponents/Favicons.php | 2 ++ src/PageComponents/Navigation.php | 2 ++ 3 files changed, 6 insertions(+) diff --git a/public/index.php b/public/index.php index 7a2c6c2f..eead26bc 100644 --- a/public/index.php +++ b/public/index.php @@ -1,5 +1,7 @@ Date: Thu, 28 Oct 2021 09:09:06 -0500 Subject: [PATCH 02/10] remove tests for deprecated classes --- tests/App_.php | 84 ---------------------------------------- tests/Environment_.php | 50 ------------------------ tests/Index_.php | 87 ------------------------------------------ 3 files changed, 221 deletions(-) delete mode 100644 tests/App_.php delete mode 100644 tests/Environment_.php delete mode 100644 tests/Index_.php diff --git a/tests/App_.php b/tests/App_.php deleted file mode 100644 index 3e8d24e6..00000000 --- a/tests/App_.php +++ /dev/null @@ -1,84 +0,0 @@ -response()->getBody(); - - $endTime = hrtime(true); - - $elapsed = $endTime - $startTime; - $ms = $elapsed/1e+6; - - expect($ms)->toBeLessThan(306); // used to be 29ms - - expect( - $body - )->toBe(<< - sub-folder | Josh Bruce's personal site

A sub-folder content

This content was successfully found.

- html - ); -}); - -test('Content is from file system', function() { - $startTime = hrtime(true); - - $body = App::init(environment())->response()->getBody(); - - $endTime = hrtime(true); - - $elapsed = $endTime - $startTime; - $ms = $elapsed/1e+6; - - expect($ms)->toBeLessThan(67); // used to be 22ms - - expect( - $body - )->toBe(<< - Josh Bruce's personal site

The domain of Josh Bruce

This content was successfully found.

- html - ); - - $startTime = hrtime(true); - - $body = App::init(environment('/does-not-exist'))->response()->getBody(); - - $endTime = hrtime(true); - - $elapsed = $endTime - $startTime; - $ms = $elapsed/1e+6; - - expect($ms)->toBeLessThan(5); - - expect( - $body - )->toBe(<< - Not found

404: Not found

We still haven’t found what you’re looking for.

- html - ); -}); - -test('Instantiation', function () { - expect( - App::init(environment())->response()->getStatusCode() - )->toBe( - 200 - ); - - expect( - App::init(environment('/does-not-exist'))->response()->getStatusCode() - )->toBe( - 404 - ); - - expect( - App::init(environment()) - )->toBeInstanceOf( - App::class - ); -})->group('app'); diff --git a/tests/Environment_.php b/tests/Environment_.php deleted file mode 100644 index e36d59d6..00000000 --- a/tests/Environment_.php +++ /dev/null @@ -1,50 +0,0 @@ -response()->getBody(); - - $endTime = hrtime(true); - - $elapsed = $endTime - $startTime; - $ms = $elapsed/1e+6; - - expect($ms)->toBeLessThan(22); - - expect( - $body - )->toBe(<< - Content error

502: Bad gateway (content)

We’re not sure what happened here but we’re pretty sure it’s on us.

Please try again later.

If this error persists, please contact Josh Bruce.

- html - ); -})->group('environment'); - -test('Verifies', function () { - expect( - Environment::init( - Server::init(serverGlobals()) - )->response()->isOk() - )->toBeTrue(); - - $serverGlobals = serverGlobals(); - $serverGlobals['CONTENT_FOLDER'] = 'does-not-exist'; - - expect( - Environment::init( - Server::init($serverGlobals) - )->response()->isOk() - )->toBeFalse(); -})->group('environment'); diff --git a/tests/Index_.php b/tests/Index_.php deleted file mode 100644 index e25ef608..00000000 --- a/tests/Index_.php +++ /dev/null @@ -1,87 +0,0 @@ -response()->isOk() - )->toBeTrue(); - - expect( - App::init( - Environment::init( - Server::init($_SERVER) - ) - )->response()->getStatusCode() - )->toBe( - 200 - ); - - $_SERVER['REQUEST_URI'] = '/does-not-exist'; - - expect( - App::init( - Environment::init( - Server::init($_SERVER) - ) - )->response()->getStatusCode() - )->toBe( - 404 - ); -})->group('index'); - -test('Environment can respond positively and negatively', function() { - expect( - Environment::init( - Server::init($_SERVER) - )->response()->isOk() - )->toBeTrue(); - - expect( - Environment::init( - Server::init($_SERVER) - )->response()->getStatusCode() - )->toBe( - 200 - ); - - $_SERVER['CONTENT_FOLDER'] = '/incorrect-folder-name'; - - expect( - Environment::init( - Server::init($_SERVER) - )->response()->getStatusCode() - )->toBe( - 502 - ); -})->group('index'); - -test('Server can respond positively and negatively', function() { - expect( - Server::init($_SERVER)->response()->isOk() - )->toBeTrue(); - - expect( - Server::init($_SERVER)->response()->getStatusCode() - )->toBe( - 200 - ); - - unset($_SERVER['APP_ENV']); - - expect( - Server::init($_SERVER)->response()->getStatusCode() - )->toBe( - 500 - ); -})->group('index'); From 4b6bd9d36d071d847fef056b3418821d7823824a Mon Sep 17 00:00:00 2001 From: Josh Bruce Date: Thu, 28 Oct 2021 09:12:27 -0500 Subject: [PATCH 03/10] unused variable and test deleted --- src/Server.php | 1 - tests/ContentTest.php | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Server.php b/src/Server.php index e6e96fe8..4533ab68 100644 --- a/src/Server.php +++ b/src/Server.php @@ -35,7 +35,6 @@ public function isMissingRequiredValues(): bool 'REQUEST_URI' ]; - $hasRequired = true; foreach ($required as $key) { if (! array_key_exists($key, $this->serverGlobals)) { return true; diff --git a/tests/ContentTest.php b/tests/ContentTest.php index df2bf33e..cbbef0e9 100644 --- a/tests/ContentTest.php +++ b/tests/ContentTest.php @@ -35,5 +35,4 @@ 'text/html' ); - expect($this->baseContent->folderIsMissing())->toBeFalse(); })->group('content'); From ce586c5ecb20a56eb91323af842fa373498061ea Mon Sep 17 00:00:00 2001 From: Josh Bruce Date: Thu, 28 Oct 2021 09:16:28 -0500 Subject: [PATCH 04/10] fix nav and add external links capability --- public/index.php | 2 +- src/PageComponents/Navigation.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/index.php b/public/index.php index eead26bc..f1417464 100644 --- a/public/index.php +++ b/public/index.php @@ -87,7 +87,7 @@ * Process HTML response: local response time 75ms (90ms with table content) */ -$markdownConverter = $markdownConverter->tables(); +$markdownConverter = $markdownConverter->tables()->externalLinks(); $headers['Content-Type'] = $content->mimeType(); diff --git a/src/PageComponents/Navigation.php b/src/PageComponents/Navigation.php index b059b0d0..8ef0a8f0 100644 --- a/src/PageComponents/Navigation.php +++ b/src/PageComponents/Navigation.php @@ -81,7 +81,7 @@ public function build(): string } return HtmlElement::nav( HtmlElement::ul(...$li) - ); + )->build(); } public function __toString(): string From 2f43963ae946ef1241b6f8ce874fbe8b88bd4a11 Mon Sep 17 00:00:00 2001 From: Josh Bruce Date: Thu, 28 Oct 2021 09:58:23 -0500 Subject: [PATCH 05/10] remove caching for redirection This should help with testing and a future where we ensure there is only one redirection that happens - at least as much as is practical --- src/Emitter.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Emitter.php b/src/Emitter.php index 5d7dd43a..b7cec316 100644 --- a/src/Emitter.php +++ b/src/Emitter.php @@ -160,7 +160,11 @@ public static function emitRedirectionResponse(string $location): void self::emitWithResponse( 301, [ - 'Location' => $location + 'Location' => $location, + 'Cache-Control' => [ + 'no-cache', + 'must-revalidate' + ] ] ); } From 651f0e5702bbb7c94dc66a74488fc669fb576dd8 Mon Sep 17 00:00:00 2001 From: Josh Bruce Date: Thu, 28 Oct 2021 10:13:45 -0500 Subject: [PATCH 06/10] Update ServerTest.php --- tests/ServerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ServerTest.php b/tests/ServerTest.php index 66f41015..10fb363a 100644 --- a/tests/ServerTest.php +++ b/tests/ServerTest.php @@ -2,7 +2,7 @@ use JoshBruce\Site\Server; -it('expected local file path', function() { +it('has expected local file path', function() { expect( Server::init(serverGlobals())->filePathForRequest() )->toBe( From e62a6579d797dd5a24f3bf40a22bae7ac7a8ace1 Mon Sep 17 00:00:00 2001 From: Josh Bruce Date: Thu, 28 Oct 2021 10:31:59 -0500 Subject: [PATCH 07/10] date blocks and titles --- public/index.php | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/public/index.php b/public/index.php index f1417464..61a5801a 100644 --- a/public/index.php +++ b/public/index.php @@ -87,7 +87,8 @@ * Process HTML response: local response time 75ms (90ms with table content) */ -$markdownConverter = $markdownConverter->tables()->externalLinks(); +$markdownConverter = $markdownConverter->withConfig(['html_input' => 'allow']) + ->tables()->externalLinks(); $headers['Content-Type'] = $content->mimeType(); @@ -95,14 +96,35 @@ $headElements[] = Eightfold\HTMLBuilder\Element::link() ->props('rel stylesheet', 'href /css/main.css'); +$markdown = $content->markdown(); + +$frontMatter = $markdownConverter->getFrontMatter($content->markdown()); + +$dateBlock = Eightfold\HTMLBuilder\Element::div( + Eightfold\HTMLBuilder\Element::p("Created on: {$frontMatter['created']}"), + Eightfold\HTMLBuilder\Element::p("Updated on: {$frontMatter['updated']}") + )->props('is dateblock'); + +$body = $markdownConverter->getBody($markdown); + +$body = $dateBlock . $body; + +if (array_key_exists('header', $frontMatter)) { + $body = "# {$frontMatter['header']}\n\n" . $body; + +} else { + $body = "# {$frontMatter['title']}\n\n" . $body; + +} + $body = Eightfold\HTMLBuilder\Document::create( - $markdownConverter->getFrontMatter($content->markdown())['title'] + $frontMatter['title'] )->head( ...$headElements )->body( JoshBruce\Site\PageComponents\Navigation::create($content) ->build(), - $markdownConverter->convert($content->markdown()) + $markdownConverter->convert($body) )->build(); JoshBruce\Site\Emitter::emitWithResponse(200, $headers, $body); From 4e3861d9175cc056d832d8b05371facf6356b1b4 Mon Sep 17 00:00:00 2001 From: Josh Bruce Date: Thu, 28 Oct 2021 10:36:30 -0500 Subject: [PATCH 08/10] copyright --- public/index.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/public/index.php b/public/index.php index 61a5801a..f3004430 100644 --- a/public/index.php +++ b/public/index.php @@ -124,7 +124,13 @@ )->body( JoshBruce\Site\PageComponents\Navigation::create($content) ->build(), - $markdownConverter->convert($body) + $markdownConverter->convert($body), + Eightfold\HTMLBuilder\Element::footer( + Eightfold\HTMLBuilder\Element::p( + 'Copyright © 2004–' . date('Y') . 'Joshua C. Bruce. ' . + 'All rights reserved.' + ) + ) )->build(); JoshBruce\Site\Emitter::emitWithResponse(200, $headers, $body); From 01c5ea55d8355c78fd69fd7c639aac13c238a911 Mon Sep 17 00:00:00 2001 From: Josh Bruce Date: Thu, 28 Oct 2021 18:56:26 -0500 Subject: [PATCH 09/10] log list capability in place --- public/index.php | 26 +++++++++++++++++++++++++- src/Content.php | 47 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 68 insertions(+), 5 deletions(-) diff --git a/public/index.php b/public/index.php index f3004430..9e41a9ab 100644 --- a/public/index.php +++ b/public/index.php @@ -100,9 +100,16 @@ $frontMatter = $markdownConverter->getFrontMatter($content->markdown()); +$updated = ''; +if (array_key_exists('updated', $frontMatter)) { + $updated = Eightfold\HTMLBuilder\Element::p( + "Updated on: {$frontMatter['updated']}" + ); +} + $dateBlock = Eightfold\HTMLBuilder\Element::div( Eightfold\HTMLBuilder\Element::p("Created on: {$frontMatter['created']}"), - Eightfold\HTMLBuilder\Element::p("Updated on: {$frontMatter['updated']}") + $updated )->props('is dateblock'); $body = $markdownConverter->getBody($markdown); @@ -117,6 +124,23 @@ } +if (array_key_exists('type', $frontMatter) and $frontMatter['type'] === 'log') { + $contents = $content->contentInSubfolders(); + krsort($contents); + $logLinks = []; + foreach ($contents as $key => $c) { + if (! str_starts_with(strval($key), '_') and $c->exists()) { + $logLinks[] = Eightfold\HTMLBuilder\Element::li( + Eightfold\HTMLBuilder\Element::a( + $c->frontMatter()['title'] + )->props('href ' . $c->pathWithoutFile()) + ); + } + } + $list = Eightfold\HTMLBuilder\Element::ul(...$logLinks)->build(); + $body = $body . $list; +} + $body = Eightfold\HTMLBuilder\Document::create( $frontMatter['title'] )->head( diff --git a/src/Content.php b/src/Content.php index 9a6386cf..dd38e6e2 100644 --- a/src/Content.php +++ b/src/Content.php @@ -4,6 +4,8 @@ namespace JoshBruce\Site; +use DirectoryIterator; + use Eightfold\Markdown\Markdown; use JoshBruce\Site; @@ -56,11 +58,24 @@ public function for(string $path): Content return $this; } + public function pathWithoutFile(): string + { + if (strpos($this->path, '.') === 0) { + return $this->path; + } + return implode('/', array_slice(explode('/', $this->path), 0, -1)); + } + public function notFound(): bool { return ! $this->exists(); } + public function exists(): bool + { + return file_exists($this->filePath()); + } + public function hasMoved(): bool { return strlen($this->redirectPath()) > 0; @@ -136,14 +151,38 @@ public function redirectPath(): string return ''; } - private function folderExists(): bool + public function contentInSubfolders(): array { - return file_exists($this->root()) and is_dir($this->root()); + $parts = explode('/', $this->path); + $parts = array_slice($parts, 0, -1); + $dirPath = implode('/', $parts); + + $folderPath = $this->root() . $dirPath; + + if (! is_dir($folderPath)) { + return []; + } + + $content = []; + foreach (new DirectoryIterator($folderPath) as $folder) { + if ($folder->isFile() or $folder->isDot()) { + // I feel continue should be named next or something. + continue; + } + $path = str_replace($this->root(), '', $folder->getPathname()); + $date = array_slice(explode('/', $path), -1); + $date = array_shift($date); + if ($date !== null) { + $clone = clone $this; + $content[$date] = $clone->for($path . '/content.md'); + } + } + return $content; } - private function exists(): bool + private function folderExists(): bool { - return file_exists($this->filePath()); + return file_exists($this->root()) and is_dir($this->root()); } private function root(): string From 2c96f1b29abee556aa4219d98b14256bb9a730b9 Mon Sep 17 00:00:00 2001 From: Josh Bruce Date: Thu, 28 Oct 2021 18:57:48 -0500 Subject: [PATCH 10/10] Update Content.php --- src/Content.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Content.php b/src/Content.php index dd38e6e2..f3c95b82 100644 --- a/src/Content.php +++ b/src/Content.php @@ -151,6 +151,9 @@ public function redirectPath(): string return ''; } + /** + * @return array + */ public function contentInSubfolders(): array { $parts = explode('/', $this->path);