From 37e5921bc1b46cd98b133668f6859922571b7a23 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sun, 25 Feb 2024 18:39:43 +0100 Subject: [PATCH 01/90] Initial feature abstract --- docs/digging-deeper/advanced-markdown.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/digging-deeper/advanced-markdown.md b/docs/digging-deeper/advanced-markdown.md index bf58e739fd1..3b13d463bed 100644 --- a/docs/digging-deeper/advanced-markdown.md +++ b/docs/digging-deeper/advanced-markdown.md @@ -156,6 +156,14 @@ anything within the path label will be rendered as HTML. This means you can add ``` ```` +### Dynamic Markdown links + +In order to create automatically resolved links from your pages and posts, you can use the special Hyde Markdown link syntax. + +For all the supported syntax options, Hyde will resolve a relative link based on the current page being rendered. + +Since this happens in our Markdown processor, this will work regardless of if you have custom HTML or Blade enabled for your site. + ### Limitations The filepaths are hidden on mobile devices using CSS to prevent them from overlapping with the code block. From 1f9912865a541e331c97f92364a10363331be61c Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sun, 25 Feb 2024 18:39:48 +0100 Subject: [PATCH 02/90] Add examples --- docs/digging-deeper/advanced-markdown.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/digging-deeper/advanced-markdown.md b/docs/digging-deeper/advanced-markdown.md index 3b13d463bed..0256ed6458f 100644 --- a/docs/digging-deeper/advanced-markdown.md +++ b/docs/digging-deeper/advanced-markdown.md @@ -164,6 +164,24 @@ For all the supported syntax options, Hyde will resolve a relative link based on Since this happens in our Markdown processor, this will work regardless of if you have custom HTML or Blade enabled for your site. +#### Resolving a route + +```markdown +[Home](hyde::route('home')) +``` + +#### Resolving a relative link + +```markdown +[Home](hyde::relativeLink('home')) +``` + +#### Resolving a media asset + +```markdown +![Image](hyde::media('image.jpg')) +``` + ### Limitations The filepaths are hidden on mobile devices using CSS to prevent them from overlapping with the code block. From 04dcd92ddbfd8bc395df8d9d40917cb378033a3c Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sun, 25 Feb 2024 18:43:05 +0100 Subject: [PATCH 03/90] Streamline examples --- docs/digging-deeper/advanced-markdown.md | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/docs/digging-deeper/advanced-markdown.md b/docs/digging-deeper/advanced-markdown.md index 0256ed6458f..bf2240e6c93 100644 --- a/docs/digging-deeper/advanced-markdown.md +++ b/docs/digging-deeper/advanced-markdown.md @@ -164,21 +164,14 @@ For all the supported syntax options, Hyde will resolve a relative link based on Since this happens in our Markdown processor, this will work regardless of if you have custom HTML or Blade enabled for your site. -#### Resolving a route - ```markdown + [Home](hyde::route('home')) -``` -#### Resolving a relative link - -```markdown + [Home](hyde::relativeLink('home')) -``` - -#### Resolving a media asset -```markdown + ![Image](hyde::media('image.jpg')) ``` From eec58870c6ff389c90244bd5f701ab52872dce78 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 17:15:06 +0200 Subject: [PATCH 04/90] Match the Hyde facade methods --- docs/digging-deeper/advanced-markdown.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/digging-deeper/advanced-markdown.md b/docs/digging-deeper/advanced-markdown.md index bf2240e6c93..fd9803663a1 100644 --- a/docs/digging-deeper/advanced-markdown.md +++ b/docs/digging-deeper/advanced-markdown.md @@ -172,7 +172,7 @@ Since this happens in our Markdown processor, this will work regardless of if yo [Home](hyde::relativeLink('home')) -![Image](hyde::media('image.jpg')) +![Image](hyde::asset('image.jpg')) ``` ### Limitations From 397da8e0045aba6e59a0104a1f83a89c919cc477 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 17:24:25 +0200 Subject: [PATCH 05/90] Create DynamicMarkdownLinksTest.php --- .../tests/Feature/DynamicMarkdownLinksTest.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 packages/framework/tests/Feature/DynamicMarkdownLinksTest.php diff --git a/packages/framework/tests/Feature/DynamicMarkdownLinksTest.php b/packages/framework/tests/Feature/DynamicMarkdownLinksTest.php new file mode 100644 index 00000000000..eae8ef2be58 --- /dev/null +++ b/packages/framework/tests/Feature/DynamicMarkdownLinksTest.php @@ -0,0 +1,18 @@ +assertTrue(true); + } +} From 63bab3b8308b95d6cabb0772a448c8690e24bfd1 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 17:17:36 +0200 Subject: [PATCH 06/90] Create DynamicMarkdownLinkProcessor.php --- .../Processing/DynamicMarkdownLinkProcessor.php | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php diff --git a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php new file mode 100644 index 00000000000..24b2415c298 --- /dev/null +++ b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php @@ -0,0 +1,10 @@ + Date: Wed, 24 Jul 2024 17:17:51 +0200 Subject: [PATCH 07/90] Implements MarkdownPostProcessorContract --- .../src/Markdown/Processing/DynamicMarkdownLinkProcessor.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php index 24b2415c298..ce913e077d5 100644 --- a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php +++ b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php @@ -4,7 +4,9 @@ namespace Hyde\Markdown\Processing; -class DynamicMarkdownLinkProcessor +use Hyde\Markdown\Contracts\MarkdownPostProcessorContract; + +class DynamicMarkdownLinkProcessor implements MarkdownPostProcessorContract { // } From a2e30520d8e03088afc0763f0167899174d209ac Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 17:24:16 +0200 Subject: [PATCH 08/90] Draft postprocess method --- .../src/Markdown/Processing/DynamicMarkdownLinkProcessor.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php index ce913e077d5..a47642414a4 100644 --- a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php +++ b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php @@ -8,5 +8,8 @@ class DynamicMarkdownLinkProcessor implements MarkdownPostProcessorContract { - // + public static function postprocess(string $html): string + { + // TODO: Implement postprocess() method. + } } From 59b06182e4716c528ec90d43d22590ece6c9be39 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 17:24:32 +0200 Subject: [PATCH 09/90] Revert "Create DynamicMarkdownLinksTest.php" This reverts commit 091a8d5c48f51af5e24686cfca3494daf79c3ba6. --- .../tests/Feature/DynamicMarkdownLinksTest.php | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 packages/framework/tests/Feature/DynamicMarkdownLinksTest.php diff --git a/packages/framework/tests/Feature/DynamicMarkdownLinksTest.php b/packages/framework/tests/Feature/DynamicMarkdownLinksTest.php deleted file mode 100644 index eae8ef2be58..00000000000 --- a/packages/framework/tests/Feature/DynamicMarkdownLinksTest.php +++ /dev/null @@ -1,18 +0,0 @@ -assertTrue(true); - } -} From 47bfef53fb5985da8123466fb055cdbcd9c90d95 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 17:26:21 +0200 Subject: [PATCH 10/90] Create DynamicMarkdownLinkProcessorTest.php --- .../Markdown/DynamicMarkdownLinkProcessorTest.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php diff --git a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php new file mode 100644 index 00000000000..4fc7c0e2f1a --- /dev/null +++ b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php @@ -0,0 +1,15 @@ + Date: Wed, 24 Jul 2024 17:33:23 +0200 Subject: [PATCH 11/90] Implement the initial dynamic markdown link feature --- .../DynamicMarkdownLinkProcessor.php | 19 ++++++- .../DynamicMarkdownLinkProcessorTest.php | 52 ++++++++++++++++++- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php index a47642414a4..3b17b28b5fc 100644 --- a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php +++ b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php @@ -4,12 +4,29 @@ namespace Hyde\Markdown\Processing; +use Hyde\Hyde; use Hyde\Markdown\Contracts\MarkdownPostProcessorContract; class DynamicMarkdownLinkProcessor implements MarkdownPostProcessorContract { public static function postprocess(string $html): string { - // TODO: Implement postprocess() method. + $patterns = [ + '/ function ($matches) { + return ' function ($matches) { + return ' function ($matches) { + return ' $replacement) { + $html = preg_replace_callback($pattern, $replacement, $html); + } + + return $html; } } diff --git a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php index 4fc7c0e2f1a..c6e42bcff2a 100644 --- a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php +++ b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php @@ -4,12 +4,62 @@ namespace Hyde\Framework\Testing\Feature\Services\Markdown; +use Hyde\Pages\InMemoryPage; use Hyde\Testing\UnitTestCase; +use Hyde\Support\Models\Route; +use Hyde\Support\Facades\Render; +use Hyde\Foundation\Facades\Routes; +use Hyde\Support\Models\RenderData; +use Hyde\Markdown\Processing\DynamicMarkdownLinkProcessor; /** * @covers \Hyde\Markdown\Processing\DynamicMarkdownLinkProcessor */ class DynamicMarkdownLinkProcessorTest extends UnitTestCase { - // + protected static bool $needsConfig = true; + protected static bool $needsKernel = true; + + protected function setUp(): void + { + parent::setUp(); + + Render::swap(new RenderData()); + + Routes::addRoute(new Route(new InMemoryPage('home'))); + } + + public function testRouteReplacement() + { + $input = '

Home

'; + $expected = '

Home

'; + $this->assertEquals($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } + + public function testRelativeLinkReplacement() + { + $input = '

About

'; + $expected = '

About

'; + $this->assertEquals($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } + + public function testAssetReplacement() + { + $input = '

Image

'; + $expected = '

Image

'; + $this->assertEquals($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } + + public function testMultipleReplacements() + { + $input = '

Home About Logo

'; + $expected = '

Home About Logo

'; + $this->assertEquals($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } + + public function testNoReplacements() + { + $input = '

This is a regular link with no Hyde syntax.

'; + $this->assertEquals($input, DynamicMarkdownLinkProcessor::postprocess($input)); + } } From 6ec38dd1f4b1fbde44ef66cd099c8829342aa8a3 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 17:45:56 +0200 Subject: [PATCH 12/90] Refactor to use strict types --- .../Markdown/Processing/DynamicMarkdownLinkProcessor.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php index 3b17b28b5fc..ef41334443b 100644 --- a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php +++ b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php @@ -11,14 +11,15 @@ class DynamicMarkdownLinkProcessor implements MarkdownPostProcessorContract { public static function postprocess(string $html): string { + /** @var array): string> $patterns */ $patterns = [ - '/ function ($matches) { + '/ function (array $matches): string { return ' function ($matches) { + '/ function (array $matches): string { return ' function ($matches) { + '/ function (array $matches): string { return ' Date: Wed, 24 Jul 2024 17:48:12 +0200 Subject: [PATCH 13/90] Extract helper method --- .../DynamicMarkdownLinkProcessor.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php index ef41334443b..52ae7a605eb 100644 --- a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php +++ b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php @@ -11,8 +11,17 @@ class DynamicMarkdownLinkProcessor implements MarkdownPostProcessorContract { public static function postprocess(string $html): string { - /** @var array): string> $patterns */ - $patterns = [ + foreach (static::patterns() as $pattern => $replacement) { + $html = preg_replace_callback($pattern, $replacement, $html); + } + + return $html; + } + + /** @return array): string> */ + protected static function patterns(): array + { + return [ '/ function (array $matches): string { return ' $replacement) { - $html = preg_replace_callback($pattern, $replacement, $html); - } - - return $html; } } From 3c91dd7958e16d4449b2322b03d94ab309e40117 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 17:49:51 +0200 Subject: [PATCH 14/90] Supress faulty inspection --- .../Services/Markdown/DynamicMarkdownLinkProcessorTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php index c6e42bcff2a..d722ca54b0e 100644 --- a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php +++ b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php @@ -1,5 +1,7 @@ Date: Wed, 24 Jul 2024 17:54:33 +0200 Subject: [PATCH 15/90] Use more readable formatting for complex test fixture --- .../Markdown/DynamicMarkdownLinkProcessorTest.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php index d722ca54b0e..183a6d7414b 100644 --- a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php +++ b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php @@ -54,8 +54,18 @@ public function testAssetReplacement() public function testMultipleReplacements() { - $input = '

Home About Logo

'; - $expected = '

Home About Logo

'; + $input = <<<'MARKDOWN' + Home + About + Logo + MARKDOWN; + + $expected = <<<'HTML' + Home + About + Logo + HTML; + $this->assertEquals($expected, DynamicMarkdownLinkProcessor::postprocess($input)); } From 33ba914f9ec938abf3cb4909a4871d2ed0811504 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 17:54:59 +0200 Subject: [PATCH 16/90] Use assert same instead of assert equals --- .../Markdown/DynamicMarkdownLinkProcessorTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php index 183a6d7414b..48026b79b39 100644 --- a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php +++ b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php @@ -35,21 +35,21 @@ public function testRouteReplacement() { $input = '

Home

'; $expected = '

Home

'; - $this->assertEquals($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); } public function testRelativeLinkReplacement() { $input = '

About

'; $expected = '

About

'; - $this->assertEquals($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); } public function testAssetReplacement() { $input = '

Image

'; $expected = '

Image

'; - $this->assertEquals($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); } public function testMultipleReplacements() @@ -66,12 +66,12 @@ public function testMultipleReplacements() Logo HTML; - $this->assertEquals($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); } public function testNoReplacements() { $input = '

This is a regular link with no Hyde syntax.

'; - $this->assertEquals($input, DynamicMarkdownLinkProcessor::postprocess($input)); + $this->assertSame($input, DynamicMarkdownLinkProcessor::postprocess($input)); } } From 15ecda86a7272dcc92ddc8a9b4485a8be0c2d86a Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 17:58:44 +0200 Subject: [PATCH 17/90] Update Markdown link support to work without single quotes --- .../Processing/DynamicMarkdownLinkProcessor.php | 12 ++++++------ .../DynamicMarkdownLinkProcessorTest.php | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php index 52ae7a605eb..bf00a9a8c1a 100644 --- a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php +++ b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php @@ -22,14 +22,14 @@ public static function postprocess(string $html): string protected static function patterns(): array { return [ - '/ function (array $matches): string { - return ' function (array $matches): string { + return ' function (array $matches): string { - return ' function (array $matches): string { + return ' function (array $matches): string { - return ' function (array $matches): string { + return 'Home

'; $expected = '

Home

'; $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + + $inputUnquoted = '

Home

'; + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputUnquoted)); } public function testRelativeLinkReplacement() @@ -43,6 +46,9 @@ public function testRelativeLinkReplacement() $input = '

About

'; $expected = '

About

'; $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + + $inputUnquoted = '

About

'; + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputUnquoted)); } public function testAssetReplacement() @@ -50,6 +56,9 @@ public function testAssetReplacement() $input = '

Image

'; $expected = '

Image

'; $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + + $inputUnquoted = '

Image

'; + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputUnquoted)); } public function testMultipleReplacements() @@ -67,6 +76,14 @@ public function testMultipleReplacements() HTML; $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + + $inputUnquoted = <<<'MARKDOWN' + Home + About + Logo + MARKDOWN; + + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputUnquoted)); } public function testNoReplacements() From 048910d6d913f591d0d951867c465d8b6cecd6ed Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 18:00:20 +0200 Subject: [PATCH 18/90] Update Markdown link support to work with double quotes --- .../DynamicMarkdownLinkProcessor.php | 6 +-- .../DynamicMarkdownLinkProcessorTest.php | 46 +++++++++++++------ 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php index bf00a9a8c1a..fe50a979784 100644 --- a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php +++ b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php @@ -22,13 +22,13 @@ public static function postprocess(string $html): string protected static function patterns(): array { return [ - '/ function (array $matches): string { + '/ function (array $matches): string { return ' function (array $matches): string { + '/ function (array $matches): string { return ' function (array $matches): string { + '/ function (array $matches): string { return 'Home

'; $expected = '

Home

'; - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + + $inputSingleQuotes = '

Home

'; + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputSingleQuotes)); + + $inputDoubleQuotes = '

Home

'; + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputDoubleQuotes)); $inputUnquoted = '

Home

'; $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputUnquoted)); @@ -43,9 +47,13 @@ public function testRouteReplacement() public function testRelativeLinkReplacement() { - $input = '

About

'; $expected = '

About

'; - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + + $inputSingleQuotes = '

About

'; + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputSingleQuotes)); + + $inputDoubleQuotes = '

About

'; + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputDoubleQuotes)); $inputUnquoted = '

About

'; $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputUnquoted)); @@ -53,9 +61,13 @@ public function testRelativeLinkReplacement() public function testAssetReplacement() { - $input = '

Image

'; $expected = '

Image

'; - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + + $inputSingleQuotes = '

Image

'; + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputSingleQuotes)); + + $inputDoubleQuotes = '

Image

'; + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputDoubleQuotes)); $inputUnquoted = '

Image

'; $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputUnquoted)); @@ -63,19 +75,27 @@ public function testAssetReplacement() public function testMultipleReplacements() { - $input = <<<'MARKDOWN' - Home - About - Logo - MARKDOWN; - $expected = <<<'HTML' Home About Logo HTML; - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + $inputSingleQuotes = <<<'MARKDOWN' + Home + About + Logo + MARKDOWN; + + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputSingleQuotes)); + + $inputDoubleQuotes = <<<'MARKDOWN' + Home + About + Logo + MARKDOWN; + + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputDoubleQuotes)); $inputUnquoted = <<<'MARKDOWN' Home From 017355f117a9475bb83eb09a54747d04b11523c5 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 18:03:16 +0200 Subject: [PATCH 19/90] Split out multiple assertions to dedicated unit tests The testMultipleReplacements method does not need to be split since we don't get any new information from testing already tested alternate syntaxes. That test is mainly for humans to visualise the applicable code better in a more real life scenario. --- .../DynamicMarkdownLinkProcessorTest.php | 97 +++++++++++-------- 1 file changed, 56 insertions(+), 41 deletions(-) diff --git a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php index 7ff8843d509..57c875b2f7b 100644 --- a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php +++ b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php @@ -33,82 +33,97 @@ protected function setUp(): void public function testRouteReplacement() { + $input = '

Home

'; $expected = '

Home

'; - $inputSingleQuotes = '

Home

'; - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputSingleQuotes)); + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } - $inputDoubleQuotes = '

Home

'; - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputDoubleQuotes)); + public function testRouteReplacementWithDoubleQuotes() + { + $input = '

Home

'; + $expected = '

Home

'; - $inputUnquoted = '

Home

'; - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputUnquoted)); + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } + + public function testRouteReplacementWithoutQuotes() + { + $input = '

Home

'; + $expected = '

Home

'; + + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); } public function testRelativeLinkReplacement() { + $input = '

About

'; $expected = '

About

'; - $inputSingleQuotes = '

About

'; - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputSingleQuotes)); + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } - $inputDoubleQuotes = '

About

'; - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputDoubleQuotes)); + public function testRelativeLinkReplacementWithDoubleQuotes() + { + $input = '

About

'; + $expected = '

About

'; - $inputUnquoted = '

About

'; - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputUnquoted)); + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } + + public function testRelativeLinkReplacementWithoutQuotes() + { + $input = '

About

'; + $expected = '

About

'; + + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); } public function testAssetReplacement() { + $input = '

Image

'; $expected = '

Image

'; - $inputSingleQuotes = '

Image

'; - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputSingleQuotes)); + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } - $inputDoubleQuotes = '

Image

'; - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputDoubleQuotes)); + public function testAssetReplacementWithDoubleQuotes() + { + $input = '

Image

'; + $expected = '

Image

'; - $inputUnquoted = '

Image

'; - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputUnquoted)); + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); } - public function testMultipleReplacements() + public function testAssetReplacementWithoutQuotes() { - $expected = <<<'HTML' - Home - About - Logo - HTML; + $input = '

Image

'; + $expected = '

Image

'; - $inputSingleQuotes = <<<'MARKDOWN' + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } + + public function testMultipleReplacements() + { + $input = <<<'MARKDOWN' Home About Logo MARKDOWN; - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputSingleQuotes)); - - $inputDoubleQuotes = <<<'MARKDOWN' - Home - About - Logo - MARKDOWN; - - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputDoubleQuotes)); - - $inputUnquoted = <<<'MARKDOWN' - Home - About - Logo - MARKDOWN; + $expected = <<<'HTML' + Home + About + Logo + HTML; - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($inputUnquoted)); + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); } public function testNoReplacements() { $input = '

This is a regular link with no Hyde syntax.

'; + $this->assertSame($input, DynamicMarkdownLinkProcessor::postprocess($input)); } } From df09449ab2e856f3fe360888382f958cf3c104bf Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 18:08:42 +0200 Subject: [PATCH 20/90] Revert "Update Markdown link support to work with double quotes" This reverts commit 048910d6d913f591d0d951867c465d8b6cecd6ed. See https://github.com/hydephp/develop/pull/1590#discussion_r1690082732 --- .../DynamicMarkdownLinkProcessor.php | 6 ++--- .../DynamicMarkdownLinkProcessorTest.php | 24 ------------------- 2 files changed, 3 insertions(+), 27 deletions(-) diff --git a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php index fe50a979784..bf00a9a8c1a 100644 --- a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php +++ b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php @@ -22,13 +22,13 @@ public static function postprocess(string $html): string protected static function patterns(): array { return [ - '/ function (array $matches): string { + '/ function (array $matches): string { return ' function (array $matches): string { + '/ function (array $matches): string { return ' function (array $matches): string { + '/ function (array $matches): string { return 'assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); } - public function testRouteReplacementWithDoubleQuotes() - { - $input = '

Home

'; - $expected = '

Home

'; - - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); - } - public function testRouteReplacementWithoutQuotes() { $input = '

Home

'; @@ -63,14 +55,6 @@ public function testRelativeLinkReplacement() $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); } - public function testRelativeLinkReplacementWithDoubleQuotes() - { - $input = '

About

'; - $expected = '

About

'; - - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); - } - public function testRelativeLinkReplacementWithoutQuotes() { $input = '

About

'; @@ -87,14 +71,6 @@ public function testAssetReplacement() $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); } - public function testAssetReplacementWithDoubleQuotes() - { - $input = '

Image

'; - $expected = '

Image

'; - - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); - } - public function testAssetReplacementWithoutQuotes() { $input = '

Image

'; From 55df5a3a4724021aab6c73a5852be8fc148eb512 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 18:10:33 +0200 Subject: [PATCH 21/90] Register the dynamic Markdown link processor --- .../Framework/Concerns/Internal/SetsUpMarkdownConverter.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/framework/src/Framework/Concerns/Internal/SetsUpMarkdownConverter.php b/packages/framework/src/Framework/Concerns/Internal/SetsUpMarkdownConverter.php index 38302778834..307c2caa81d 100644 --- a/packages/framework/src/Framework/Concerns/Internal/SetsUpMarkdownConverter.php +++ b/packages/framework/src/Framework/Concerns/Internal/SetsUpMarkdownConverter.php @@ -8,6 +8,7 @@ use Hyde\Markdown\Processing\BladeDownProcessor; use Hyde\Markdown\Processing\ShortcodeProcessor; use Hyde\Markdown\Processing\CodeblockFilepathProcessor; +use Hyde\Markdown\Processing\DynamicMarkdownLinkProcessor; use Torchlight\Commonmark\V2\TorchlightExtension; use function array_merge; @@ -73,6 +74,8 @@ protected function registerPostProcessors(): void CodeblockFilepathProcessor::class, Config::getBool('markdown.features.codeblock_filepaths', true) ); + + $this->registerPostProcessor(DynamicMarkdownLinkProcessor::class); } protected function registerPreProcessor(string $class, bool $when = true): void From 16051f7e2c2bab364f8de18adb1b33aef72b9d4a Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 18:11:05 +0200 Subject: [PATCH 22/90] Reapply "Create DynamicMarkdownLinksTest.php" This reverts commit 59b06182e4716c528ec90d43d22590ece6c9be39. --- .../tests/Feature/DynamicMarkdownLinksTest.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 packages/framework/tests/Feature/DynamicMarkdownLinksTest.php diff --git a/packages/framework/tests/Feature/DynamicMarkdownLinksTest.php b/packages/framework/tests/Feature/DynamicMarkdownLinksTest.php new file mode 100644 index 00000000000..eae8ef2be58 --- /dev/null +++ b/packages/framework/tests/Feature/DynamicMarkdownLinksTest.php @@ -0,0 +1,18 @@ +assertTrue(true); + } +} From b0fe2bb0708e4971fa830da78874f2419da426bf Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 18:11:34 +0200 Subject: [PATCH 23/90] Rename test to DynamicMarkdownLinksFeatureTest --- ...arkdownLinksTest.php => DynamicMarkdownLinksFeatureTest.php} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename packages/framework/tests/Feature/{DynamicMarkdownLinksTest.php => DynamicMarkdownLinksFeatureTest.php} (79%) diff --git a/packages/framework/tests/Feature/DynamicMarkdownLinksTest.php b/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php similarity index 79% rename from packages/framework/tests/Feature/DynamicMarkdownLinksTest.php rename to packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php index eae8ef2be58..66814d5b4af 100644 --- a/packages/framework/tests/Feature/DynamicMarkdownLinksTest.php +++ b/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php @@ -9,7 +9,7 @@ /** * @covers \Hyde\Hyde */ -class DynamicMarkdownLinksTest extends TestCase +class DynamicMarkdownLinksFeatureTest extends TestCase { public function testExample() { From 69a5277a239a874c8cb48037f72b000cb3749df7 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 18:12:34 +0200 Subject: [PATCH 24/90] Set up coverage --- .../tests/Feature/DynamicMarkdownLinksFeatureTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php b/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php index 66814d5b4af..0d186b56e45 100644 --- a/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php +++ b/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php @@ -7,7 +7,8 @@ use Hyde\Testing\TestCase; /** - * @covers \Hyde\Hyde + * @covers \Hyde\Markdown\Processing\DynamicMarkdownLinkProcessor + * @covers \Hyde\Framework\Concerns\Internal\SetsUpMarkdownConverter */ class DynamicMarkdownLinksFeatureTest extends TestCase { From 6a7f46a9497844d4fe762e101075332eaa9a942c Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 18:12:57 +0200 Subject: [PATCH 25/90] Add test crosslinks --- .../framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php | 2 ++ .../Services/Markdown/DynamicMarkdownLinkProcessorTest.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php b/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php index 0d186b56e45..87aafdc3007 100644 --- a/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php +++ b/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php @@ -9,6 +9,8 @@ /** * @covers \Hyde\Markdown\Processing\DynamicMarkdownLinkProcessor * @covers \Hyde\Framework\Concerns\Internal\SetsUpMarkdownConverter + * + * @see \Hyde\Framework\Testing\Feature\Services\Markdown\DynamicMarkdownLinkProcessorTest */ class DynamicMarkdownLinksFeatureTest extends TestCase { diff --git a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php index e87afe8ee2c..ff7bb6923ef 100644 --- a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php +++ b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php @@ -16,6 +16,8 @@ /** * @covers \Hyde\Markdown\Processing\DynamicMarkdownLinkProcessor + * + * @see \Hyde\Framework\Testing\Feature\DynamicMarkdownLinksFeatureTest */ class DynamicMarkdownLinkProcessorTest extends UnitTestCase { From 85860164032a6c5efa81b2701fe44103be264055 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 18:15:23 +0200 Subject: [PATCH 26/90] Match heredoc name to type --- .../Services/Markdown/DynamicMarkdownLinkProcessorTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php index ff7bb6923ef..04f53ca365d 100644 --- a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php +++ b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php @@ -83,11 +83,11 @@ public function testAssetReplacementWithoutQuotes() public function testMultipleReplacements() { - $input = <<<'MARKDOWN' + $input = <<<'HTML' Home About Logo - MARKDOWN; + HTML; $expected = <<<'HTML' Home From e943c198b4c4eece221224664f0c5e8270409bdf Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 18:44:58 +0200 Subject: [PATCH 27/90] Implement the basic test --- .../DynamicMarkdownLinksFeatureTest.php | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php b/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php index 87aafdc3007..66ca829ad27 100644 --- a/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php +++ b/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php @@ -1,10 +1,16 @@ assertTrue(true); + $input = <<<'MARKDOWN' + [Home](hyde::route('home')) + [About](hyde::relativeLink('about')) + ![Logo](hyde::asset('logo.png')) + + [Home](hyde::route(home)) + [About](hyde::relativeLink(about)) + ![Logo](hyde::asset(logo.png)) + MARKDOWN; + + $expected = <<<'HTML' +

Home + About + Logo

+

Home + About + Logo

+ + HTML; + + $this->assertSame($expected, Hyde::markdown($input)->toHtml()); } } From d489d9020f85b3a7c8ed6d0653139a8aa7ba59ab Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 18:45:24 +0200 Subject: [PATCH 28/90] Generate more tests with Claude --- .../DynamicMarkdownLinksFeatureTest.php | 103 +++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php b/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php index 66ca829ad27..10a2e96c5ac 100644 --- a/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php +++ b/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php @@ -28,7 +28,7 @@ protected function setUp(): void Routes::addRoute(new Route(new InMemoryPage('blog/post'))); } - public function testDynamicMarkdownLinks() + public function testBasicDynamicMarkdownLinks() { $input = <<<'MARKDOWN' [Home](hyde::route('home')) @@ -52,4 +52,105 @@ public function testDynamicMarkdownLinks() $this->assertSame($expected, Hyde::markdown($input)->toHtml()); } + + public function testDynamicMarkdownLinksWithDoubleQuotes() + { + $input = <<<'MARKDOWN' + [Home](hyde::route("home")) + [About](hyde::relativeLink("about")) + ![Logo](hyde::asset("logo.png")) + MARKDOWN; + + $expected = <<<'HTML' +

Home + About + Logo

+ + HTML; + + $this->assertSame($expected, Hyde::markdown($input)->toHtml()); + } + + public function testDynamicMarkdownLinksInParagraphs() + { + $input = <<<'MARKDOWN' + This is a paragraph with a [link to home](hyde::route('home')) and an [about link](hyde::relativeLink('about')). + + Another paragraph with an ![image](hyde::asset('image.jpg')). + MARKDOWN; + + $expected = <<<'HTML' +

This is a paragraph with a link to home and an about link.

+

Another paragraph with an image.

+ + HTML; + + $this->assertSame($expected, Hyde::markdown($input)->toHtml()); + } + + public function testDynamicMarkdownLinksInLists() + { + $input = <<<'MARKDOWN' + - [Home](hyde::route('home')) + - [About](hyde::relativeLink('about')) + - ![Logo](hyde::asset('logo.png')) + MARKDOWN; + + $expected = <<<'HTML' + + + HTML; + + $this->assertSame($expected, Hyde::markdown($input)->toHtml()); + } + + public function testDynamicMarkdownLinksWithNestedRoutes() + { + $input = <<<'MARKDOWN' + [Blog Post](hyde::route('blog/post')) + [Relative Blog](hyde::relativeLink('blog/post')) + MARKDOWN; + + $expected = <<<'HTML' +

Blog Post + Relative Blog

+ + HTML; + + $this->assertSame($expected, Hyde::markdown($input)->toHtml()); + } + + public function testMixOfDynamicAndRegularMarkdownLinks() + { + $input = <<<'MARKDOWN' + [Home](hyde::route('home')) + [External](https://example.com) + [About](hyde::relativeLink('about')) + [Regular](regular-link.html) + ![Logo](hyde::asset('logo.png')) + ![External Image](https://example.com/image.jpg) + MARKDOWN; + + $expected = <<<'HTML' +

Home + External + About + Regular + Logo + External Image

+ + HTML; + + $this->assertSame($expected, Hyde::markdown($input)->toHtml()); + } } From a8aeb8bf91e0e1d7d86ec81199df1780882c2b5a Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 18:45:40 +0200 Subject: [PATCH 29/90] Skip unsupported test See https://github.com/hydephp/develop/pull/1590#discussion_r1690082732 --- .../framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php b/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php index 10a2e96c5ac..5034aecda8a 100644 --- a/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php +++ b/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php @@ -55,6 +55,8 @@ public function testBasicDynamicMarkdownLinks() public function testDynamicMarkdownLinksWithDoubleQuotes() { + $this->markTestSkipped('https://github.com/hydephp/develop/pull/1590#discussion_r1690082732'); + $input = <<<'MARKDOWN' [Home](hyde::route("home")) [About](hyde::relativeLink("about")) From b10b55a5d67c3300f6fa2ff42f09939831cf54e8 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 18:48:11 +0200 Subject: [PATCH 30/90] Add fault tolerance testing --- .../DynamicMarkdownLinkProcessorTest.php | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php index 04f53ca365d..6f7ee4bb102 100644 --- a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php +++ b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php @@ -104,4 +104,91 @@ public function testNoReplacements() $this->assertSame($input, DynamicMarkdownLinkProcessor::postprocess($input)); } + + public function testMalformedRouteLink() + { + $input = '

Malformed Home

'; + $expected = '

Malformed Home

'; + + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } + + public function testMalformedRelativeLink() + { + $input = '

Malformed About

'; + $expected = '

Malformed About

'; + + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } + + public function testMalformedAssetLink() + { + $input = '

Malformed Image

'; + $expected = '

Malformed Image

'; + + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } + + public function testEmptyRouteLink() + { + $input = '

Empty Route

'; + $expected = '

Empty Route

'; + + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } + + public function testEmptyRelativeLink() + { + $input = '

Empty Relative Link

'; + $expected = '

Empty Relative Link

'; + + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } + + public function testEmptyAssetLink() + { + $input = '

Empty Asset

'; + $expected = '

Empty Asset

'; + + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } + + public function testMixedValidAndInvalidLinks() + { + $input = <<<'HTML' + Valid Home + Invalid Route + Valid About + Invalid Relative + Valid Logo + Invalid Asset + HTML; + + $expected = <<<'HTML' + Valid Home + Invalid Route + Valid About + Invalid Relative + Valid Logo + Invalid Asset + HTML; + + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } + + public function testMalformedHydeSyntax() + { + $input = '

Malformed Hyde Syntax

'; + $expected = '

Malformed Hyde Syntax

'; + + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } + + public function testNonExistentRouteFunction() + { + $input = '

Non-existent Function

'; + $expected = '

Non-existent Function

'; + + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } } From d105152f3e9b19eca36d6f98767a3d371c027318 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 18:48:17 +0200 Subject: [PATCH 31/90] Section test code --- .../Services/Markdown/DynamicMarkdownLinkProcessorTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php index 6f7ee4bb102..e5790ea88d6 100644 --- a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php +++ b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php @@ -105,6 +105,8 @@ public function testNoReplacements() $this->assertSame($input, DynamicMarkdownLinkProcessor::postprocess($input)); } + // Fault tolerance tests + public function testMalformedRouteLink() { $input = '

Malformed Home

'; From f2d02fbd33c07d7d07a6feb86a0f41c377b446a7 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 19:01:32 +0200 Subject: [PATCH 32/90] Add more fault tolerance tests --- .../DynamicMarkdownLinkProcessorTest.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php index e5790ea88d6..c917bc2e1ab 100644 --- a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php +++ b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php @@ -115,6 +115,22 @@ public function testMalformedRouteLink() $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); } + public function testMalformedRouteLink2() + { + $input = '

Malformed Home

'; + $expected = '

Malformed Home

'; + + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } + + public function testMalformedRouteLink3() + { + $input = '

Malformed Home

'; + $expected = '

Malformed Home

'; + + $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); + } + public function testMalformedRelativeLink() { $input = '

Malformed About

'; From ad20f39262517d90b3453f2dd442fef9cbd19208 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 19:07:01 +0200 Subject: [PATCH 33/90] Throw an exception for non existent routes --- .../Processing/DynamicMarkdownLinkProcessor.php | 11 ++++++++++- .../Markdown/DynamicMarkdownLinkProcessorTest.php | 10 ++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php index bf00a9a8c1a..d6b9796d344 100644 --- a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php +++ b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php @@ -5,6 +5,7 @@ namespace Hyde\Markdown\Processing; use Hyde\Hyde; +use Hyde\Framework\Exceptions\RouteNotFoundException; use Hyde\Markdown\Contracts\MarkdownPostProcessorContract; class DynamicMarkdownLinkProcessor implements MarkdownPostProcessorContract @@ -23,7 +24,15 @@ protected static function patterns(): array { return [ '/ function (array $matches): string { - return ' function (array $matches): string { return 'assertSame($input, DynamicMarkdownLinkProcessor::postprocess($input)); } + public function testNonExistentRouteThrowsException() + { + $this->expectException(RouteNotFoundException::class); + $this->expectExceptionMessage('Route [non-existent] not found.'); + + $input = '

Non-existent Route

'; + DynamicMarkdownLinkProcessor::postprocess($input); + } + // Fault tolerance tests public function testMalformedRouteLink() From 61a552beb06f43ae0f8055105a89643154183df0 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 19:10:37 +0200 Subject: [PATCH 34/90] Extract helper method --- .../DynamicMarkdownLinkProcessor.php | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php index d6b9796d344..b9d3c37a10e 100644 --- a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php +++ b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php @@ -5,6 +5,7 @@ namespace Hyde\Markdown\Processing; use Hyde\Hyde; +use Hyde\Support\Models\Route; use Hyde\Framework\Exceptions\RouteNotFoundException; use Hyde\Markdown\Contracts\MarkdownPostProcessorContract; @@ -25,12 +26,7 @@ protected static function patterns(): array return [ '/ function (array $matches): string { $route = Hyde::route($matches[2]); - if ($route === null) { - // While the other patterns work regardless of if input is valid, - // this method returns null, which silently fails to an empty string. - // So we instead throw an exception to alert the developer of the issue. - throw new RouteNotFoundException($matches[2]); - } + static::validateRouteExists($route, $matches[2]); return ' Date: Wed, 24 Jul 2024 19:10:49 +0200 Subject: [PATCH 35/90] Add newline --- .../src/Markdown/Processing/DynamicMarkdownLinkProcessor.php | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php index b9d3c37a10e..2b48b86c203 100644 --- a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php +++ b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php @@ -26,6 +26,7 @@ protected static function patterns(): array return [ '/ function (array $matches): string { $route = Hyde::route($matches[2]); + static::validateRouteExists($route, $matches[2]); return ' Date: Wed, 24 Jul 2024 19:11:08 +0200 Subject: [PATCH 36/90] Add newline --- .../src/Markdown/Processing/DynamicMarkdownLinkProcessor.php | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php index 2b48b86c203..2c2eb91cd66 100644 --- a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php +++ b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php @@ -46,6 +46,7 @@ protected static function validateRouteExists(?Route $route, $routeKey): void // While the other patterns work regardless of if input is valid, // this method returns null, which silently fails to an empty string. // So we instead throw an exception to alert the developer of the issue. + throw new RouteNotFoundException($routeKey); } } From 8e1e51678bb3609e1c396443500b920b39860339 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 19:17:17 +0200 Subject: [PATCH 37/90] Try to find the faulty line --- .../Framework/Exceptions/RouteNotFoundException.php | 12 ++++++++++++ .../Processing/DynamicMarkdownLinkProcessor.php | 12 +++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/packages/framework/src/Framework/Exceptions/RouteNotFoundException.php b/packages/framework/src/Framework/Exceptions/RouteNotFoundException.php index 1f173d27f78..4e8c05e3d45 100644 --- a/packages/framework/src/Framework/Exceptions/RouteNotFoundException.php +++ b/packages/framework/src/Framework/Exceptions/RouteNotFoundException.php @@ -20,4 +20,16 @@ public function __construct(?string $routeKey = null) { parent::__construct($routeKey ? sprintf('Route [%s] not found.', $routeKey) : $this->message); } + + /** + * @interal + * + * @experimental + * + * @codeCoverageIgnore + */ + public function setErroredFile(string $path): void + { + $this->message = rtrim($this->message, '.').sprintf(' (in file [%s])', $path); + } } diff --git a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php index 2c2eb91cd66..c983ca3f638 100644 --- a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php +++ b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php @@ -6,6 +6,7 @@ use Hyde\Hyde; use Hyde\Support\Models\Route; +use Hyde\Support\Facades\Render; use Hyde\Framework\Exceptions\RouteNotFoundException; use Hyde\Markdown\Contracts\MarkdownPostProcessorContract; @@ -47,7 +48,16 @@ protected static function validateRouteExists(?Route $route, $routeKey): void // this method returns null, which silently fails to an empty string. // So we instead throw an exception to alert the developer of the issue. - throw new RouteNotFoundException($routeKey); + $exception = new RouteNotFoundException($routeKey); + + // In order to show the developer where this error is, we try to find the faulty Markdown file. + $page = Render::getPage(); + if ($page !== null) { + $path = $page->getSourcePath(); + $exception->setErroredFile($path); + } + + throw $exception; } } } From 12383155c8773356e37a0566ee731bfb1c393012 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 19:25:11 +0200 Subject: [PATCH 38/90] Try to find the line number of the error --- .../Framework/Exceptions/RouteNotFoundException.php | 7 +++++-- .../Processing/DynamicMarkdownLinkProcessor.php | 12 +++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/framework/src/Framework/Exceptions/RouteNotFoundException.php b/packages/framework/src/Framework/Exceptions/RouteNotFoundException.php index 4e8c05e3d45..61b408b7c0d 100644 --- a/packages/framework/src/Framework/Exceptions/RouteNotFoundException.php +++ b/packages/framework/src/Framework/Exceptions/RouteNotFoundException.php @@ -28,8 +28,11 @@ public function __construct(?string $routeKey = null) * * @codeCoverageIgnore */ - public function setErroredFile(string $path): void + public function setErroredFile(string $path, int $line = 0): void { - $this->message = rtrim($this->message, '.').sprintf(' (in file [%s])', $path); + $this->message = rtrim($this->message, '.').sprintf(' (in file %s)', $path); + + $this->file = realpath($path) ?: $path; + $this->line = $line; } } diff --git a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php index c983ca3f638..598ec42eb78 100644 --- a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php +++ b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php @@ -5,8 +5,10 @@ namespace Hyde\Markdown\Processing; use Hyde\Hyde; +use Hyde\Facades\Filesystem; use Hyde\Support\Models\Route; use Hyde\Support\Facades\Render; +use Illuminate\Support\Facades\File; use Hyde\Framework\Exceptions\RouteNotFoundException; use Hyde\Markdown\Contracts\MarkdownPostProcessorContract; @@ -54,7 +56,15 @@ protected static function validateRouteExists(?Route $route, $routeKey): void $page = Render::getPage(); if ($page !== null) { $path = $page->getSourcePath(); - $exception->setErroredFile($path); + $contents = Filesystem::getContents($path); + // Try to find the line number of the error. + $lineNumber = strpos($contents, $routeKey); + if ($lineNumber !== false) { + $lineNumber = substr_count(substr($contents, 0, $lineNumber), "\n") + 1; + $exception->setErroredFile($path, $lineNumber); + } else { + $exception->setErroredFile($path); + } } throw $exception; From 5fa57910d5a8e5ef2b1e7e36a9cb669ddd137ecd Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 19:27:09 +0200 Subject: [PATCH 39/90] Extract method --- .../DynamicMarkdownLinkProcessor.php | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php index 598ec42eb78..8d7d0967930 100644 --- a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php +++ b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php @@ -53,21 +53,33 @@ protected static function validateRouteExists(?Route $route, $routeKey): void $exception = new RouteNotFoundException($routeKey); // In order to show the developer where this error is, we try to find the faulty Markdown file. - $page = Render::getPage(); - if ($page !== null) { - $path = $page->getSourcePath(); - $contents = Filesystem::getContents($path); - // Try to find the line number of the error. - $lineNumber = strpos($contents, $routeKey); - if ($lineNumber !== false) { - $lineNumber = substr_count(substr($contents, 0, $lineNumber), "\n") + 1; - $exception->setErroredFile($path, $lineNumber); - } else { - $exception->setErroredFile($path); - } - } + self::tryToFindErroredLine($routeKey, $exception); throw $exception; } } + + /** + * @interal If we use more features like these we may want to wrap the RouteNotFoundException in a custom MarkdownPageException. + * + * @experimental + * + * @codeCoverageIgnore + */ + protected static function tryToFindErroredLine($routeKey, RouteNotFoundException $exception): void + { + $page = Render::getPage(); + if ($page !== null) { + $path = $page->getSourcePath(); + $contents = Filesystem::getContents($path); + // Try to find the line number of the error. + $lineNumber = strpos($contents, $routeKey); + if ($lineNumber !== false) { + $lineNumber = substr_count(substr($contents, 0, $lineNumber), "\n") + 1; + $exception->setErroredFile($path, $lineNumber); + } else { + $exception->setErroredFile($path); + } + } + } } From 475c8efe2f1ce15f643204b26174d009e7dd47fe Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 19:43:14 +0200 Subject: [PATCH 40/90] Test the line finding --- .../DynamicMarkdownLinkProcessor.php | 4 +-- .../DynamicMarkdownLinksFeatureTest.php | 26 +++++++++++++++++++ .../DynamicMarkdownLinkProcessorTest.php | 16 ++++++++++++ 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php index 8d7d0967930..458bc3c9d39 100644 --- a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php +++ b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php @@ -63,13 +63,11 @@ protected static function validateRouteExists(?Route $route, $routeKey): void * @interal If we use more features like these we may want to wrap the RouteNotFoundException in a custom MarkdownPageException. * * @experimental - * - * @codeCoverageIgnore */ protected static function tryToFindErroredLine($routeKey, RouteNotFoundException $exception): void { $page = Render::getPage(); - if ($page !== null) { + if ($page !== null && Filesystem::exists($page->getSourcePath())) { $path = $page->getSourcePath(); $contents = Filesystem::getContents($path); // Try to find the line number of the error. diff --git a/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php b/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php index 5034aecda8a..9b0e51151ea 100644 --- a/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php +++ b/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php @@ -9,8 +9,11 @@ use Hyde\Hyde; use Hyde\Testing\TestCase; use Hyde\Pages\InMemoryPage; +use Hyde\Pages\MarkdownPage; use Hyde\Support\Models\Route; use Hyde\Foundation\Facades\Routes; +use Hyde\Framework\Actions\StaticPageBuilder; +use Hyde\Framework\Exceptions\RouteNotFoundException; /** * @covers \Hyde\Markdown\Processing\DynamicMarkdownLinkProcessor @@ -155,4 +158,27 @@ public function testMixOfDynamicAndRegularMarkdownLinks() $this->assertSame($expected, Hyde::markdown($input)->toHtml()); } + + public function testNonExistentRouteThrowsExceptionWithLineLocationWhenRenderingAPage() + { + $this->file('_pages/test.md', <<<'MARKDOWN' + Some + Extra + Newlines + + [test](hyde::route('non-existent')) + + And some more text. + MARKDOWN); + + try { + $page = MarkdownPage::parse('test'); + StaticPageBuilder::handle($page); + } catch (RouteNotFoundException $exception) { + $this->assertSame('Route [non-existent] not found (in file _pages/test.md)', $exception->getMessage()); + $this->assertSame(realpath(Hyde::path('_pages/test.md')), $exception->getFile()); + $this->assertSame(5, $exception->getLine()); + $this->assertIsString($exception->getFile()); + } + } } diff --git a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php index 4ebc368e653..42192af9878 100644 --- a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php +++ b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php @@ -6,7 +6,9 @@ namespace Hyde\Framework\Testing\Feature\Services\Markdown; +use Mockery; use Hyde\Pages\InMemoryPage; +use Hyde\Pages\MarkdownPage; use Hyde\Testing\UnitTestCase; use Hyde\Support\Models\Route; use Hyde\Support\Facades\Render; @@ -115,6 +117,20 @@ public function testNonExistentRouteThrowsException() DynamicMarkdownLinkProcessor::postprocess($input); } + public function testNonExistentRouteThrowsExceptionWithGracefulLineFindingWhenNoFileSourceExists() + { + $instance = Mockery::mock(RenderData::class); + $instance->shouldReceive('getPage')->andReturn(new MarkdownPage('test')); + + Render::swap($instance); + + $this->expectException(RouteNotFoundException::class); + $this->expectExceptionMessage('Route [non-existent] not found.'); + + $input = '

Non-existent Route

'; + DynamicMarkdownLinkProcessor::postprocess($input); + } + // Fault tolerance tests public function testMalformedRouteLink() From 5da5b2fd5cc8fc62d3cf915810fa4c479a5543b8 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 20:42:44 +0200 Subject: [PATCH 41/90] Revert out of scope line finder See https://github.com/hydephp/develop/pull/1590#discussion_r1690205820 Revert "Extract helper method" This reverts commit 61a552beb06f43ae0f8055105a89643154183df0. Revert "Test the line finding" This reverts commit 475c8efe2f1ce15f643204b26174d009e7dd47fe. Revert "Extract method" This reverts commit 5fa57910d5a8e5ef2b1e7e36a9cb669ddd137ecd. Revert "Try to find the line number of the error" This reverts commit 12383155c8773356e37a0566ee731bfb1c393012. Revert "Try to find the faulty line" This reverts commit 8e1e51678bb3609e1c396443500b920b39860339. Revert "Add newline" This reverts commit 80edd88d786f813e9d72cb66714ae714cd6ce820. Revert "Add newline" This reverts commit ee000ced31862c0ba2e26bfe0af007991c708150. --- .../Exceptions/RouteNotFoundException.php | 15 ------ .../DynamicMarkdownLinkProcessor.php | 50 +++---------------- .../DynamicMarkdownLinksFeatureTest.php | 26 ---------- .../DynamicMarkdownLinkProcessorTest.php | 16 ------ 4 files changed, 6 insertions(+), 101 deletions(-) diff --git a/packages/framework/src/Framework/Exceptions/RouteNotFoundException.php b/packages/framework/src/Framework/Exceptions/RouteNotFoundException.php index 61b408b7c0d..1f173d27f78 100644 --- a/packages/framework/src/Framework/Exceptions/RouteNotFoundException.php +++ b/packages/framework/src/Framework/Exceptions/RouteNotFoundException.php @@ -20,19 +20,4 @@ public function __construct(?string $routeKey = null) { parent::__construct($routeKey ? sprintf('Route [%s] not found.', $routeKey) : $this->message); } - - /** - * @interal - * - * @experimental - * - * @codeCoverageIgnore - */ - public function setErroredFile(string $path, int $line = 0): void - { - $this->message = rtrim($this->message, '.').sprintf(' (in file %s)', $path); - - $this->file = realpath($path) ?: $path; - $this->line = $line; - } } diff --git a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php index 458bc3c9d39..d6b9796d344 100644 --- a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php +++ b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php @@ -5,10 +5,6 @@ namespace Hyde\Markdown\Processing; use Hyde\Hyde; -use Hyde\Facades\Filesystem; -use Hyde\Support\Models\Route; -use Hyde\Support\Facades\Render; -use Illuminate\Support\Facades\File; use Hyde\Framework\Exceptions\RouteNotFoundException; use Hyde\Markdown\Contracts\MarkdownPostProcessorContract; @@ -29,8 +25,12 @@ protected static function patterns(): array return [ '/ function (array $matches): string { $route = Hyde::route($matches[2]); - - static::validateRouteExists($route, $matches[2]); + if ($route === null) { + // While the other patterns work regardless of if input is valid, + // this method returns null, which silently fails to an empty string. + // So we instead throw an exception to alert the developer of the issue. + throw new RouteNotFoundException($matches[2]); + } return 'getSourcePath())) { - $path = $page->getSourcePath(); - $contents = Filesystem::getContents($path); - // Try to find the line number of the error. - $lineNumber = strpos($contents, $routeKey); - if ($lineNumber !== false) { - $lineNumber = substr_count(substr($contents, 0, $lineNumber), "\n") + 1; - $exception->setErroredFile($path, $lineNumber); - } else { - $exception->setErroredFile($path); - } - } - } } diff --git a/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php b/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php index 9b0e51151ea..5034aecda8a 100644 --- a/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php +++ b/packages/framework/tests/Feature/DynamicMarkdownLinksFeatureTest.php @@ -9,11 +9,8 @@ use Hyde\Hyde; use Hyde\Testing\TestCase; use Hyde\Pages\InMemoryPage; -use Hyde\Pages\MarkdownPage; use Hyde\Support\Models\Route; use Hyde\Foundation\Facades\Routes; -use Hyde\Framework\Actions\StaticPageBuilder; -use Hyde\Framework\Exceptions\RouteNotFoundException; /** * @covers \Hyde\Markdown\Processing\DynamicMarkdownLinkProcessor @@ -158,27 +155,4 @@ public function testMixOfDynamicAndRegularMarkdownLinks() $this->assertSame($expected, Hyde::markdown($input)->toHtml()); } - - public function testNonExistentRouteThrowsExceptionWithLineLocationWhenRenderingAPage() - { - $this->file('_pages/test.md', <<<'MARKDOWN' - Some - Extra - Newlines - - [test](hyde::route('non-existent')) - - And some more text. - MARKDOWN); - - try { - $page = MarkdownPage::parse('test'); - StaticPageBuilder::handle($page); - } catch (RouteNotFoundException $exception) { - $this->assertSame('Route [non-existent] not found (in file _pages/test.md)', $exception->getMessage()); - $this->assertSame(realpath(Hyde::path('_pages/test.md')), $exception->getFile()); - $this->assertSame(5, $exception->getLine()); - $this->assertIsString($exception->getFile()); - } - } } diff --git a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php index 42192af9878..4ebc368e653 100644 --- a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php +++ b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php @@ -6,9 +6,7 @@ namespace Hyde\Framework\Testing\Feature\Services\Markdown; -use Mockery; use Hyde\Pages\InMemoryPage; -use Hyde\Pages\MarkdownPage; use Hyde\Testing\UnitTestCase; use Hyde\Support\Models\Route; use Hyde\Support\Facades\Render; @@ -117,20 +115,6 @@ public function testNonExistentRouteThrowsException() DynamicMarkdownLinkProcessor::postprocess($input); } - public function testNonExistentRouteThrowsExceptionWithGracefulLineFindingWhenNoFileSourceExists() - { - $instance = Mockery::mock(RenderData::class); - $instance->shouldReceive('getPage')->andReturn(new MarkdownPage('test')); - - Render::swap($instance); - - $this->expectException(RouteNotFoundException::class); - $this->expectExceptionMessage('Route [non-existent] not found.'); - - $input = '

Non-existent Route

'; - DynamicMarkdownLinkProcessor::postprocess($input); - } - // Fault tolerance tests public function testMalformedRouteLink() From 2bf321c0b080d8dca574bcf9bacffc5031a13199 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 20:49:53 +0200 Subject: [PATCH 42/90] Generate new documentation with Claude --- docs/digging-deeper/advanced-markdown.md | 53 +++++++++++++++++++++--- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/docs/digging-deeper/advanced-markdown.md b/docs/digging-deeper/advanced-markdown.md index fd9803663a1..5b4f1225019 100644 --- a/docs/digging-deeper/advanced-markdown.md +++ b/docs/digging-deeper/advanced-markdown.md @@ -156,25 +156,66 @@ anything within the path label will be rendered as HTML. This means you can add ``` ```` -### Dynamic Markdown links +## Dynamic Markdown Links -In order to create automatically resolved links from your pages and posts, you can use the special Hyde Markdown link syntax. +HydePHP provides a powerful feature for creating automatically resolved links within your pages and posts using a special Hyde Markdown link syntax. This feature allows you to generate dynamic links that are resolved based on the current page being rendered. -For all the supported syntax options, Hyde will resolve a relative link based on the current page being rendered. +### Usage -Since this happens in our Markdown processor, this will work regardless of if you have custom HTML or Blade enabled for your site. +You can use the following syntax options in your Markdown files: ```markdown [Home](hyde::route('home')) -[Home](hyde::relativeLink('home')) +[About](hyde::relativeLink('about')) -![Image](hyde::asset('image.jpg')) +![Logo](hyde::asset('logo.png')) ``` +### How It Works + +The Hyde Markdown processor handles these special links during the conversion process. This means that the feature works regardless of whether you have custom HTML or Blade enabled for your site. + +Here's what each function does: + +- `hyde::route()`: Generates a link to a specific route in your Hyde site. +- `hyde::relativeLink()`: Creates a relative link to another page. +- `hyde::asset()`: Resolves the path to a media asset in your site. + +### Behavior and Error Handling + +- If the specified route or asset exists, Hyde will generate the correct URL. +- If a route specified in `hyde::route()` does not exist, a `RouteNotFoundException` will be thrown. This helps catch errors early in the development process. + +>info Note: The exception throwing behavior for non-existent routes is designed to provide immediate feedback during development. In production environments, you may want to handle these exceptions gracefully. + +### Best Practices + +1. Always double-check that the pages or assets you're linking to exist in your project. +2. Use meaningful names for your routes to make your Markdown more readable and maintainable. +3. Consider using `hyde::relativeLink()` for local navigation if your site structure might change. + +### Customization + +You can customize how Hyde handles dynamic links by modifying the `config/hyde.php` file. For example, you might want to change how non-existent routes are handled in production: + +```php +// filepath: config/hyde.php +'dynamic_links' => [ + 'throw_exception_on_missing_route' => env('APP_ENV') === 'local', +], +``` + +### Limitations + +- The dynamic link syntax is only processed within Markdown files. It won't work in plain HTML or Blade templates. +- Make sure to use the correct syntax (`hyde::function('parameter')`) as other variations may not be recognized. + +By using these dynamic Markdown links, you can create more maintainable and flexible content, allowing your site structure to evolve without breaking internal links. + ### Limitations The filepaths are hidden on mobile devices using CSS to prevent them from overlapping with the code block. From 6d43f736811ecee50b6016195fa5f010367064a2 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 20:50:03 +0200 Subject: [PATCH 43/90] Proof generated documentation --- docs/digging-deeper/advanced-markdown.md | 40 +++++------------------- 1 file changed, 8 insertions(+), 32 deletions(-) diff --git a/docs/digging-deeper/advanced-markdown.md b/docs/digging-deeper/advanced-markdown.md index 5b4f1225019..26432b77999 100644 --- a/docs/digging-deeper/advanced-markdown.md +++ b/docs/digging-deeper/advanced-markdown.md @@ -165,7 +165,7 @@ HydePHP provides a powerful feature for creating automatically resolved links wi You can use the following syntax options in your Markdown files: ```markdown - + [Home](hyde::route('home')) @@ -179,42 +179,18 @@ You can use the following syntax options in your Markdown files: The Hyde Markdown processor handles these special links during the conversion process. This means that the feature works regardless of whether you have custom HTML or Blade enabled for your site. -Here's what each function does: - -- `hyde::route()`: Generates a link to a specific route in your Hyde site. -- `hyde::relativeLink()`: Creates a relative link to another page. -- `hyde::asset()`: Resolves the path to a media asset in your site. - -### Behavior and Error Handling - -- If the specified route or asset exists, Hyde will generate the correct URL. -- If a route specified in `hyde::route()` does not exist, a `RouteNotFoundException` will be thrown. This helps catch errors early in the development process. - ->info Note: The exception throwing behavior for non-existent routes is designed to provide immediate feedback during development. In production environments, you may want to handle these exceptions gracefully. - -### Best Practices - -1. Always double-check that the pages or assets you're linking to exist in your project. -2. Use meaningful names for your routes to make your Markdown more readable and maintainable. -3. Consider using `hyde::relativeLink()` for local navigation if your site structure might change. -### Customization - -You can customize how Hyde handles dynamic links by modifying the `config/hyde.php` file. For example, you might want to change how non-existent routes are handled in production: +Here's what each function does: -```php -// filepath: config/hyde.php -'dynamic_links' => [ - 'throw_exception_on_missing_route' => env('APP_ENV') === 'local', -], -``` +- `hyde::route()`: Generates a link to a specific route in your Hyde site. This is equivalent to `{{ Hyde::route('route.name') }}` in Blade (But we throw if the route doesn't exist). +- `hyde::relativeLink()`: Creates a relative link to another page. This is equivalent to `{{ Hyde::relativeLink('path') }}` in Blade. +- `hyde::asset()`: Resolves the path to a media asset in your site. This is equivalent to `{{ Hyde::asset('path') }}` in Blade. -### Limitations +By using these dynamic Markdown links, you can create more maintainable and flexible content, allowing your site structure to evolve without breaking internal links. -- The dynamic link syntax is only processed within Markdown files. It won't work in plain HTML or Blade templates. -- Make sure to use the correct syntax (`hyde::function('parameter')`) as other variations may not be recognized. +### Considerations -By using these dynamic Markdown links, you can create more maintainable and flexible content, allowing your site structure to evolve without breaking internal links. +**Note:** For the route helper we throw an exception if the route doesn't exist. This is to provide immediate feedback during development. ### Limitations From 5e96cda5fe2443a42ebb5894e5ca4f347b797a82 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 21:04:44 +0200 Subject: [PATCH 44/90] Streamline documentation --- docs/digging-deeper/advanced-markdown.md | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/docs/digging-deeper/advanced-markdown.md b/docs/digging-deeper/advanced-markdown.md index 26432b77999..72ebe98d07e 100644 --- a/docs/digging-deeper/advanced-markdown.md +++ b/docs/digging-deeper/advanced-markdown.md @@ -158,7 +158,7 @@ anything within the path label will be rendered as HTML. This means you can add ## Dynamic Markdown Links -HydePHP provides a powerful feature for creating automatically resolved links within your pages and posts using a special Hyde Markdown link syntax. This feature allows you to generate dynamic links that are resolved based on the current page being rendered. +HydePHP provides a powerful feature for automatically resolving dynamic links within your pages and posts using a special Hyde Markdown link syntax, designed to match the syntax of the `Hyde` facade. ### Usage @@ -175,22 +175,25 @@ You can use the following syntax options in your Markdown files: ![Logo](hyde::asset('logo.png')) ``` -### How It Works +By using these dynamic Markdown links, you can create more maintainable and flexible content, allowing your site structure to evolve without breaking internal links. The feature is always enabled in the Markdown converter. -The Hyde Markdown processor handles these special links during the conversion process. This means that the feature works regardless of whether you have custom HTML or Blade enabled for your site. +### Breakdown -Here's what each function does: +The example above is equivalent to the following Blade syntax: -- `hyde::route()`: Generates a link to a specific route in your Hyde site. This is equivalent to `{{ Hyde::route('route.name') }}` in Blade (But we throw if the route doesn't exist). -- `hyde::relativeLink()`: Creates a relative link to another page. This is equivalent to `{{ Hyde::relativeLink('path') }}` in Blade. -- `hyde::asset()`: Resolves the path to a media asset in your site. This is equivalent to `{{ Hyde::asset('path') }}` in Blade. +```blade + +{{ Hyde::route('route.name') ?? throw new RouteNotFoundException() }} -By using these dynamic Markdown links, you can create more maintainable and flexible content, allowing your site structure to evolve without breaking internal links. + +{{ Hyde::relativeLink('path') }} -### Considerations + +{{ Hyde::asset('path') }} +``` -**Note:** For the route helper we throw an exception if the route doesn't exist. This is to provide immediate feedback during development. +As you can see, we throw an exception if the route doesn't exist, to provide immediate feedback during development. ### Limitations From a2b256b6c5f77435e8d90fb41cd82594fc6ff4af Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 21:05:06 +0200 Subject: [PATCH 45/90] Fix documentation location --- docs/digging-deeper/advanced-markdown.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/digging-deeper/advanced-markdown.md b/docs/digging-deeper/advanced-markdown.md index 72ebe98d07e..60123b9d3f0 100644 --- a/docs/digging-deeper/advanced-markdown.md +++ b/docs/digging-deeper/advanced-markdown.md @@ -156,6 +156,11 @@ anything within the path label will be rendered as HTML. This means you can add ``` ```` +### Limitations + +The filepaths are hidden on mobile devices using CSS to prevent them from overlapping with the code block. + + ## Dynamic Markdown Links HydePHP provides a powerful feature for automatically resolving dynamic links within your pages and posts using a special Hyde Markdown link syntax, designed to match the syntax of the `Hyde` facade. @@ -195,9 +200,6 @@ The example above is equivalent to the following Blade syntax: As you can see, we throw an exception if the route doesn't exist, to provide immediate feedback during development. -### Limitations - -The filepaths are hidden on mobile devices using CSS to prevent them from overlapping with the code block. ## Configuration From 9589bc17d1165cbc577e298d4500c7aeb9a2c48d Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 21:12:32 +0200 Subject: [PATCH 46/90] Remove dynamic relative link Markdown feature offering little value Can't see too big of a use case for this --- docs/digging-deeper/advanced-markdown.md | 6 --- .../DynamicMarkdownLinkProcessor.php | 3 -- .../DynamicMarkdownLinksFeatureTest.php | 20 ++-------- .../DynamicMarkdownLinkProcessorTest.php | 38 ------------------- 4 files changed, 3 insertions(+), 64 deletions(-) diff --git a/docs/digging-deeper/advanced-markdown.md b/docs/digging-deeper/advanced-markdown.md index 60123b9d3f0..f8d59d14267 100644 --- a/docs/digging-deeper/advanced-markdown.md +++ b/docs/digging-deeper/advanced-markdown.md @@ -173,9 +173,6 @@ You can use the following syntax options in your Markdown files: [Home](hyde::route('home')) - -[About](hyde::relativeLink('about')) - ![Logo](hyde::asset('logo.png')) ``` @@ -191,9 +188,6 @@ The example above is equivalent to the following Blade syntax: {{ Hyde::route('route.name') ?? throw new RouteNotFoundException() }} - -{{ Hyde::relativeLink('path') }} - {{ Hyde::asset('path') }} ``` diff --git a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php index d6b9796d344..0bbe7643826 100644 --- a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php +++ b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php @@ -34,9 +34,6 @@ protected static function patterns(): array return ' function (array $matches): string { - return ' function (array $matches): string { return 'Home - About Logo

Home - About Logo

HTML; @@ -59,13 +55,11 @@ public function testDynamicMarkdownLinksWithDoubleQuotes() $input = <<<'MARKDOWN' [Home](hyde::route("home")) - [About](hyde::relativeLink("about")) ![Logo](hyde::asset("logo.png")) MARKDOWN; $expected = <<<'HTML'

Home - About Logo

HTML; @@ -76,13 +70,13 @@ public function testDynamicMarkdownLinksWithDoubleQuotes() public function testDynamicMarkdownLinksInParagraphs() { $input = <<<'MARKDOWN' - This is a paragraph with a [link to home](hyde::route('home')) and an [about link](hyde::relativeLink('about')). + This is a paragraph with a [link to home](hyde::route('home')). Another paragraph with an ![image](hyde::asset('image.jpg')). MARKDOWN; $expected = <<<'HTML' -

This is a paragraph with a link to home and an about link.

+

This is a paragraph with a link to home.

Another paragraph with an image.

HTML; @@ -94,7 +88,6 @@ public function testDynamicMarkdownLinksInLists() { $input = <<<'MARKDOWN' - [Home](hyde::route('home')) - - [About](hyde::relativeLink('about')) - ![Logo](hyde::asset('logo.png')) MARKDOWN; @@ -104,9 +97,6 @@ public function testDynamicMarkdownLinksInLists() Home
  • - About -
  • -
  • Logo
  • @@ -120,12 +110,10 @@ public function testDynamicMarkdownLinksWithNestedRoutes() { $input = <<<'MARKDOWN' [Blog Post](hyde::route('blog/post')) - [Relative Blog](hyde::relativeLink('blog/post')) MARKDOWN; $expected = <<<'HTML' -

    Blog Post - Relative Blog

    +

    Blog Post

    HTML; @@ -137,7 +125,6 @@ public function testMixOfDynamicAndRegularMarkdownLinks() $input = <<<'MARKDOWN' [Home](hyde::route('home')) [External](https://example.com) - [About](hyde::relativeLink('about')) [Regular](regular-link.html) ![Logo](hyde::asset('logo.png')) ![External Image](https://example.com/image.jpg) @@ -146,7 +133,6 @@ public function testMixOfDynamicAndRegularMarkdownLinks() $expected = <<<'HTML'

    Home External - About Regular Logo External Image

    diff --git a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php index 4ebc368e653..daca2d7ea34 100644 --- a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php +++ b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php @@ -50,22 +50,6 @@ public function testRouteReplacementWithoutQuotes() $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); } - public function testRelativeLinkReplacement() - { - $input = '

    About

    '; - $expected = '

    About

    '; - - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); - } - - public function testRelativeLinkReplacementWithoutQuotes() - { - $input = '

    About

    '; - $expected = '

    About

    '; - - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); - } - public function testAssetReplacement() { $input = '

    Image

    '; @@ -86,13 +70,11 @@ public function testMultipleReplacements() { $input = <<<'HTML' Home - About Logo HTML; $expected = <<<'HTML' Home - About Logo HTML; @@ -141,14 +123,6 @@ public function testMalformedRouteLink3() $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); } - public function testMalformedRelativeLink() - { - $input = '

    Malformed About

    '; - $expected = '

    Malformed About

    '; - - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); - } - public function testMalformedAssetLink() { $input = '

    Malformed Image

    '; @@ -165,14 +139,6 @@ public function testEmptyRouteLink() $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); } - public function testEmptyRelativeLink() - { - $input = '

    Empty Relative Link

    '; - $expected = '

    Empty Relative Link

    '; - - $this->assertSame($expected, DynamicMarkdownLinkProcessor::postprocess($input)); - } - public function testEmptyAssetLink() { $input = '

    Empty Asset

    '; @@ -186,8 +152,6 @@ public function testMixedValidAndInvalidLinks() $input = <<<'HTML' Valid Home Invalid Route - Valid About - Invalid Relative Valid Logo Invalid Asset HTML; @@ -195,8 +159,6 @@ public function testMixedValidAndInvalidLinks() $expected = <<<'HTML' Valid Home Invalid Route - Valid About - Invalid Relative Valid Logo Invalid Asset HTML; From d4d8762640544f0402c651797715b0303384940e Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 24 Jul 2024 21:47:29 +0200 Subject: [PATCH 47/90] New proof of concept --- docs/digging-deeper/advanced-markdown.md | 38 ++++-- .../DynamicMarkdownLinkProcessor.php | 59 +++++---- .../DynamicMarkdownLinksFeatureTest.php | 83 ++++++------ .../DynamicMarkdownLinkProcessorTest.php | 122 ++++++------------ 4 files changed, 141 insertions(+), 161 deletions(-) diff --git a/docs/digging-deeper/advanced-markdown.md b/docs/digging-deeper/advanced-markdown.md index f8d59d14267..ce04af98bfd 100644 --- a/docs/digging-deeper/advanced-markdown.md +++ b/docs/digging-deeper/advanced-markdown.md @@ -163,7 +163,7 @@ The filepaths are hidden on mobile devices using CSS to prevent them from overla ## Dynamic Markdown Links -HydePHP provides a powerful feature for automatically resolving dynamic links within your pages and posts using a special Hyde Markdown link syntax, designed to match the syntax of the `Hyde` facade. +HydePHP provides a powerful feature for automatically resolving dynamic links within your pages and posts using source file paths, which are then converted to the appropriate routes in the built site. ### Usage @@ -171,29 +171,43 @@ You can use the following syntax options in your Markdown files: ```markdown -[Home](hyde::route('home')) +[Home](/_pages/index.blade.php) -![Logo](hyde::asset('logo.png')) +![Logo](/_media/logo.svg) ``` By using these dynamic Markdown links, you can create more maintainable and flexible content, allowing your site structure to evolve without breaking internal links. The feature is always enabled in the Markdown converter. +### How It Works -### Breakdown +When you use a source file path in your Markdown links, HydePHP will automatically convert it to the appropriate route or asset path in the built site. For example: -The example above is equivalent to the following Blade syntax: +- `/_pages/index.blade.php` will be converted to `index.html` +- `/_pages/blog/post.blade.php` will be converted to `blog/post.html` +- `/_media/logo.svg` will be converted to `media/logo.svg` -```blade - -{{ Hyde::route('route.name') ?? throw new RouteNotFoundException() }} +This conversion happens during the build process, ensuring that your links are always up-to-date with your current site structure. - -{{ Hyde::asset('path') }} -``` +### Benefits + +1. **IDE Support**: By using actual file paths, you get better IDE support, including autocompletion and error checking. +2. **Syntax Highlighting**: Your Markdown editor can provide proper syntax highlighting for these links, as they use standard Markdown syntax. +3. **Easy Navigation**: You can easily navigate to the source files by clicking on the links in your IDE. + +### Limitations + +- This syntax doesn't support linking to dynamic routes. For such cases, you may need to use a different approach. +- If you move or rename source files, make sure to update any Markdown links referencing them to avoid broken links. +- While this approach provides better IDE support and syntax highlighting, it does couple your content to your project structure. Consider this trade-off when deciding to use this feature. + +### Best Practices -As you can see, we throw an exception if the route doesn't exist, to provide immediate feedback during development. +1. Always use the leading slash (`/`) in your links to ensure consistency and avoid potential issues with relative paths. +2. Keep your file structure organized and consistent to make it easier to manage links. +3. Regularly check for broken links in your content, especially after moving or renaming files. +By following these guidelines and understanding the limitations, you can effectively use dynamic Markdown links to create more maintainable and flexible content in your HydePHP projects. ## Configuration diff --git a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php index 0bbe7643826..5ab0541ad2c 100644 --- a/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php +++ b/packages/framework/src/Markdown/Processing/DynamicMarkdownLinkProcessor.php @@ -5,38 +5,49 @@ namespace Hyde\Markdown\Processing; use Hyde\Hyde; -use Hyde\Framework\Exceptions\RouteNotFoundException; +use Illuminate\Support\Str; +use Hyde\Support\Filesystem\MediaFile; use Hyde\Markdown\Contracts\MarkdownPostProcessorContract; class DynamicMarkdownLinkProcessor implements MarkdownPostProcessorContract { public static function postprocess(string $html): string { - foreach (static::patterns() as $pattern => $replacement) { - $html = preg_replace_callback($pattern, $replacement, $html); + // Todo cache in static property bound to kernel version (but evaluation is tied to rendering page) + + $map = []; + + /** @var \Hyde\Support\Models\Route $route */ + foreach (Hyde::routes() as $route) { + $map[$route->getSourcePath()] = $route; } - return $html; - } + foreach ($map as $sourcePath => $route) { + $patterns = [ + '', + '', + ]; - /** @return array): string> */ - protected static function patterns(): array - { - return [ - '/ function (array $matches): string { - $route = Hyde::route($matches[2]); - if ($route === null) { - // While the other patterns work regardless of if input is valid, - // this method returns null, which silently fails to an empty string. - // So we instead throw an exception to alert the developer of the issue. - throw new RouteNotFoundException($matches[2]); - } - - return ' function (array $matches): string { - return '', $html); + } + + // maybe we just need to cache this, as the kernel is already a singleton, but this is not + $assetMap = []; + + foreach (MediaFile::all() as $mediaFile) { + $assetMap[$mediaFile->getPath()] = $mediaFile; + } + + foreach ($assetMap as $path => $mediaFile) { + $patterns = [ + 'getPath(), '_media/'); + $html = str_replace($patterns, 'Home - Logo

    -

    Home - Logo

    - - HTML; + unlink('_media/logo.png'); + unlink('_media/image.jpg'); - $this->assertSame($expected, Hyde::markdown($input)->toHtml()); + parent::tearDownAfterClass(); } - public function testDynamicMarkdownLinksWithDoubleQuotes() + public function testBasicDynamicMarkdownLinks() { - $this->markTestSkipped('https://github.com/hydephp/develop/pull/1590#discussion_r1690082732'); - $input = <<<'MARKDOWN' - [Home](hyde::route("home")) - ![Logo](hyde::asset("logo.png")) + [Home](/_pages/index.blade.php) + ![Logo](/_media/logo.png) MARKDOWN; $expected = <<<'HTML' -

    Home +

    Home Logo

    HTML; @@ -70,13 +53,13 @@ public function testDynamicMarkdownLinksWithDoubleQuotes() public function testDynamicMarkdownLinksInParagraphs() { $input = <<<'MARKDOWN' - This is a paragraph with a [link to home](hyde::route('home')). + This is a paragraph with a [link to home](/_pages/index.blade.php). - Another paragraph with an ![image](hyde::asset('image.jpg')). + Another paragraph with an ![image](/_media/image.jpg). MARKDOWN; $expected = <<<'HTML' -

    This is a paragraph with a link to home.

    +

    This is a paragraph with a link to home.

    Another paragraph with an image.

    HTML; @@ -87,14 +70,14 @@ public function testDynamicMarkdownLinksInParagraphs() public function testDynamicMarkdownLinksInLists() { $input = <<<'MARKDOWN' - - [Home](hyde::route('home')) - - ![Logo](hyde::asset('logo.png')) + - [Home](/_pages/index.blade.php) + - ![Logo](/_media/logo.png) MARKDOWN; $expected = <<<'HTML'