From 56940818c9b03f9e5cefd9464c602c88708cbbdd Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sat, 21 Dec 2024 22:43:57 +0100 Subject: [PATCH 01/12] Create a new `Hyde::makeSlug()` helper --- .../src/Foundation/Concerns/ImplementsStringHelpers.php | 5 +++++ packages/framework/tests/Feature/HydeKernelTest.php | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/packages/framework/src/Foundation/Concerns/ImplementsStringHelpers.php b/packages/framework/src/Foundation/Concerns/ImplementsStringHelpers.php index a5910e8bf71..d89fb58f49e 100644 --- a/packages/framework/src/Foundation/Concerns/ImplementsStringHelpers.php +++ b/packages/framework/src/Foundation/Concerns/ImplementsStringHelpers.php @@ -38,6 +38,11 @@ public static function makeTitle(string $value): string )); } + public static function makeSlug(string $value): string + { + return Str::slug($value); + } + public static function normalizeNewlines(string $string): string { return str_replace("\r\n", "\n", $string); diff --git a/packages/framework/tests/Feature/HydeKernelTest.php b/packages/framework/tests/Feature/HydeKernelTest.php index d2e58f58abc..feb93d38c52 100644 --- a/packages/framework/tests/Feature/HydeKernelTest.php +++ b/packages/framework/tests/Feature/HydeKernelTest.php @@ -108,6 +108,11 @@ public function testMakeTitleHelperReturnsTitleFromPageSlug() $this->assertSame('Foo Bar', Hyde::makeTitle('foo-bar')); } + public function testMakeSlugHelperReturnsSlugFromTitle() + { + $this->assertSame('foo-bar', Hyde::makeSlug('Foo Bar')); + } + public function testNormalizeNewlinesReplacesCarriageReturnsWithUnixEndings() { $this->assertSame("foo\nbar\nbaz", Hyde::normalizeNewlines("foo\nbar\r\nbaz")); From 8b1f0d0013c81950da2bed67064dbe6f571e3c19 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sat, 21 Dec 2024 22:45:54 +0100 Subject: [PATCH 02/12] Create unit test for the slug generation helper --- .../tests/Feature/HydeKernelTest.php | 1 + .../Unit/HydeHelperFacadeMakeSlugTest.php | 61 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 packages/framework/tests/Unit/HydeHelperFacadeMakeSlugTest.php diff --git a/packages/framework/tests/Feature/HydeKernelTest.php b/packages/framework/tests/Feature/HydeKernelTest.php index feb93d38c52..ea18c156855 100644 --- a/packages/framework/tests/Feature/HydeKernelTest.php +++ b/packages/framework/tests/Feature/HydeKernelTest.php @@ -32,6 +32,7 @@ * @covers \Hyde\Hyde * * @see \Hyde\Framework\Testing\Unit\HydeHelperFacadeMakeTitleTest + * @see \Hyde\Framework\Testing\Unit\HydeHelperFacadeMakeSlugTest * @see \Hyde\Framework\Testing\Feature\HydeExtensionFeatureTest */ class HydeKernelTest extends TestCase diff --git a/packages/framework/tests/Unit/HydeHelperFacadeMakeSlugTest.php b/packages/framework/tests/Unit/HydeHelperFacadeMakeSlugTest.php new file mode 100644 index 00000000000..b82ca5b1f4d --- /dev/null +++ b/packages/framework/tests/Unit/HydeHelperFacadeMakeSlugTest.php @@ -0,0 +1,61 @@ +assertSame('hello-world', Hyde::makeSlug('Hello World')); + } + + public function testMakeSlugHelperConvertsKebabCaseToSlug() + { + $this->assertSame('hello-world', Hyde::makeSlug('hello-world')); + } + + public function testMakeSlugHelperConvertsSnakeCaseToSlug() + { + $this->assertSame('hello-world', Hyde::makeSlug('hello_world')); + } + + public function testMakeSlugHelperConvertsCamelCaseToSlug() + { + $this->markTestSkipped('Not supported yet.'); + $this->assertSame('hello-world', Hyde::makeSlug('helloWorld')); + } + + public function testMakeSlugHelperConvertsPascalCaseToSlug() + { + $this->markTestSkipped('Not supported yet.'); + $this->assertSame('hello-world', Hyde::makeSlug('HelloWorld')); + } + + public function testMakeSlugHelperHandlesMultipleSpaces() + { + $this->assertSame('hello-world', Hyde::makeSlug('Hello World')); + } + + public function testMakeSlugHelperHandlesSpecialCharacters() + { + $this->assertSame('hello-world', Hyde::makeSlug('Hello & World!')); + } + + public function testMakeSlugHelperConvertsUppercaseToLowercase() + { + $this->assertSame('hello-world', Hyde::makeSlug('HELLO WORLD')); + $this->assertSame('hello-world', Hyde::makeSlug('HELLO_WORLD')); + } + + public function testMakeSlugHelperHandlesNumbers() + { + $this->assertSame('hello-world-123', Hyde::makeSlug('Hello World 123')); + } +} From cb90a4af9c229b809ca5aa800d6018f6422f4e78 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sat, 21 Dec 2024 22:47:40 +0100 Subject: [PATCH 03/12] Use our slug generation helper --- .../src/Framework/Actions/CreatesNewMarkdownPostFile.php | 4 ++-- .../src/Framework/Actions/CreatesNewPageSourceFile.php | 2 +- .../Framework/Features/Navigation/DocumentationSidebar.php | 5 ++--- .../framework/src/Framework/Features/Navigation/NavItem.php | 3 +-- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/framework/src/Framework/Actions/CreatesNewMarkdownPostFile.php b/packages/framework/src/Framework/Actions/CreatesNewMarkdownPostFile.php index 3f1f4ea9625..f524ded7c5b 100644 --- a/packages/framework/src/Framework/Actions/CreatesNewMarkdownPostFile.php +++ b/packages/framework/src/Framework/Actions/CreatesNewMarkdownPostFile.php @@ -6,9 +6,9 @@ use Hyde\Framework\Exceptions\FileConflictException; use Hyde\Facades\Filesystem; +use Hyde\Hyde; use Hyde\Pages\MarkdownPost; use Illuminate\Support\Carbon; -use Illuminate\Support\Str; /** * Offloads logic for the make:post command. @@ -48,7 +48,7 @@ public function __construct(string $title, ?string $description, ?string $catego $this->customContent = $customContent; $this->date = Carbon::make($date ?? Carbon::now())->format('Y-m-d H:i'); - $this->identifier = Str::slug($title); + $this->identifier = Hyde::makeSlug($title); } /** diff --git a/packages/framework/src/Framework/Actions/CreatesNewPageSourceFile.php b/packages/framework/src/Framework/Actions/CreatesNewPageSourceFile.php index ccb0fb6f809..aa9355a6f46 100644 --- a/packages/framework/src/Framework/Actions/CreatesNewPageSourceFile.php +++ b/packages/framework/src/Framework/Actions/CreatesNewPageSourceFile.php @@ -81,7 +81,7 @@ protected function fileName(string $title): string } // And return a slug made from just the title without the subdirectory - return Str::slug(basename($title)); + return Hyde::makeSlug(basename($title)); } protected function normalizeSubdirectory(string $title): string diff --git a/packages/framework/src/Framework/Features/Navigation/DocumentationSidebar.php b/packages/framework/src/Framework/Features/Navigation/DocumentationSidebar.php index 919b93434a6..2808fccf51d 100644 --- a/packages/framework/src/Framework/Features/Navigation/DocumentationSidebar.php +++ b/packages/framework/src/Framework/Features/Navigation/DocumentationSidebar.php @@ -11,7 +11,6 @@ use Hyde\Support\Facades\Render; use Hyde\Support\Models\Route; use Illuminate\Support\Collection; -use Illuminate\Support\Str; use function collect; @@ -48,13 +47,13 @@ public function getGroups(): array public function getItemsInGroup(?string $group): Collection { return $this->items->filter(function (NavItem $item) use ($group): bool { - return ($item->getGroup() === $group) || ($item->getGroup() === Str::slug($group)); + return ($item->getGroup() === $group) || ($item->getGroup() === Hyde::makeSlug($group)); })->sortBy('navigation.priority')->values(); } public function isGroupActive(string $group): bool { - return Str::slug(Render::getPage()->navigationMenuGroup()) === $group + return Hyde::makeSlug(Render::getPage()->navigationMenuGroup()) === $group || $this->isPageIndexPage() && $this->shouldIndexPageBeActive($group); } diff --git a/packages/framework/src/Framework/Features/Navigation/NavItem.php b/packages/framework/src/Framework/Features/Navigation/NavItem.php index 7a57b554282..a3fe8932c1b 100644 --- a/packages/framework/src/Framework/Features/Navigation/NavItem.php +++ b/packages/framework/src/Framework/Features/Navigation/NavItem.php @@ -7,7 +7,6 @@ use Hyde\Foundation\Facades\Routes; use Hyde\Hyde; use Hyde\Support\Models\Route; -use Illuminate\Support\Str; use Stringable; /** @@ -133,6 +132,6 @@ protected static function getRouteGroup(Route $route): ?string protected static function normalizeGroupKey(?string $group): ?string { - return $group ? Str::slug($group) : null; + return $group ? Hyde::makeSlug($group) : null; } } From a0a8632366391074ec7954e2ec6c08c1666438b1 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sat, 21 Dec 2024 22:50:46 +0100 Subject: [PATCH 04/12] Expand slug generation helper to support more input cases --- .../src/Foundation/Concerns/ImplementsStringHelpers.php | 3 +++ packages/framework/tests/Unit/HydeHelperFacadeMakeSlugTest.php | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/framework/src/Foundation/Concerns/ImplementsStringHelpers.php b/packages/framework/src/Foundation/Concerns/ImplementsStringHelpers.php index d89fb58f49e..ab6c2496cbb 100644 --- a/packages/framework/src/Foundation/Concerns/ImplementsStringHelpers.php +++ b/packages/framework/src/Foundation/Concerns/ImplementsStringHelpers.php @@ -40,6 +40,9 @@ public static function makeTitle(string $value): string public static function makeSlug(string $value): string { + // Expand camelCase and PascalCase to separate words + $value = preg_replace('/([a-z])([A-Z])/', '$1 $2', $value); + return Str::slug($value); } diff --git a/packages/framework/tests/Unit/HydeHelperFacadeMakeSlugTest.php b/packages/framework/tests/Unit/HydeHelperFacadeMakeSlugTest.php index b82ca5b1f4d..d4e4b724525 100644 --- a/packages/framework/tests/Unit/HydeHelperFacadeMakeSlugTest.php +++ b/packages/framework/tests/Unit/HydeHelperFacadeMakeSlugTest.php @@ -28,13 +28,11 @@ public function testMakeSlugHelperConvertsSnakeCaseToSlug() public function testMakeSlugHelperConvertsCamelCaseToSlug() { - $this->markTestSkipped('Not supported yet.'); $this->assertSame('hello-world', Hyde::makeSlug('helloWorld')); } public function testMakeSlugHelperConvertsPascalCaseToSlug() { - $this->markTestSkipped('Not supported yet.'); $this->assertSame('hello-world', Hyde::makeSlug('HelloWorld')); } From db4a454817aa0296e942efd7a2154ee2cfef0bd5 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sun, 22 Dec 2024 10:12:18 +0100 Subject: [PATCH 05/12] Transliterate international characters when generating slugs --- .../Concerns/ImplementsStringHelpers.php | 3 + .../Unit/HydeHelperFacadeMakeSlugTest.php | 72 +++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/packages/framework/src/Foundation/Concerns/ImplementsStringHelpers.php b/packages/framework/src/Foundation/Concerns/ImplementsStringHelpers.php index ab6c2496cbb..f95dc622fb3 100644 --- a/packages/framework/src/Foundation/Concerns/ImplementsStringHelpers.php +++ b/packages/framework/src/Foundation/Concerns/ImplementsStringHelpers.php @@ -43,6 +43,9 @@ public static function makeSlug(string $value): string // Expand camelCase and PascalCase to separate words $value = preg_replace('/([a-z])([A-Z])/', '$1 $2', $value); + // Transliterate international characters to ASCII + $value = Str::transliterate($value); + return Str::slug($value); } diff --git a/packages/framework/tests/Unit/HydeHelperFacadeMakeSlugTest.php b/packages/framework/tests/Unit/HydeHelperFacadeMakeSlugTest.php index d4e4b724525..0d1279ccb9c 100644 --- a/packages/framework/tests/Unit/HydeHelperFacadeMakeSlugTest.php +++ b/packages/framework/tests/Unit/HydeHelperFacadeMakeSlugTest.php @@ -56,4 +56,76 @@ public function testMakeSlugHelperHandlesNumbers() { $this->assertSame('hello-world-123', Hyde::makeSlug('Hello World 123')); } + + public function testMakeSlugHelperTransliteratesChineseCharacters() + { + $this->assertSame('ni-hao-shi-jie', Hyde::makeSlug('你好世界')); + } + + public function testMakeSlugHelperTransliteratesJapaneseCharacters() + { + $this->assertSame('konnichihashi-jie', Hyde::makeSlug('こんにちは世界')); + } + + public function testMakeSlugHelperTransliteratesKoreanCharacters() + { + $this->assertSame('annyeongsegye', Hyde::makeSlug('안녕세계')); + } + + public function testMakeSlugHelperTransliteratesArabicCharacters() + { + $this->assertSame('mrhb-bllm', Hyde::makeSlug('مرحبا بالعالم')); + } + + public function testMakeSlugHelperTransliteratesRussianCharacters() + { + $this->assertSame('privet-mir', Hyde::makeSlug('Привет мир')); + } + + public function testMakeSlugHelperTransliteratesAccentedLatinCharacters() + { + $this->assertSame('hello-world', Hyde::makeSlug('hèllô wórld')); + $this->assertSame('uber-strasse', Hyde::makeSlug('über straße')); + } + + public function testMakeSlugHelperHandlesMixedScripts() + { + $this->assertSame('hello-ni-hao-world', Hyde::makeSlug('Hello 你好 World')); + $this->assertSame('privet-world', Hyde::makeSlug('Привет World')); + } + + public function testMakeSlugHelperHandlesEmojis() + { + $this->assertSame('hello-world', Hyde::makeSlug('Hello 👋 World')); + $this->assertSame('world', Hyde::makeSlug('😊 World')); + } + + public function testMakeSlugHelperHandlesComplexMixedInput() + { + $this->assertSame( + 'hello-ni-hao-privet-bonjour-world-123', + Hyde::makeSlug('Hello 你好 Привет Bonjóur World 123!') + ); + } + + public function testMakeSlugHelperHandlesEdgeCases() + { + $this->assertSame('', Hyde::makeSlug('')); + $this->assertSame('at', Hyde::makeSlug('!@#$%^&*()')); + $this->assertSame('', Hyde::makeSlug('... ...')); + $this->assertSame('multiple-dashes', Hyde::makeSlug('multiple---dashes')); + } + + public function testMakeSlugHelperPreservesValidCharacters() + { + $this->assertSame('abc-123', Hyde::makeSlug('abc-123')); + $this->assertSame('test-slug', Hyde::makeSlug('test-slug')); + } + + public function testMakeSlugHelperHandlesWhitespace() + { + $this->assertSame('trim-spaces', Hyde::makeSlug(' trim spaces ')); + $this->assertSame('newline-test', Hyde::makeSlug("newline\ntest")); + $this->assertSame('tab-test', Hyde::makeSlug("tab\ttest")); + } } From 5b201eba5b37b9a23f3b3dd0ac3cdcd661573359 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sun, 22 Dec 2024 10:19:03 +0100 Subject: [PATCH 06/12] Refactor method to make it more readable --- .../Framework/Features/Navigation/DocumentationSidebar.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/framework/src/Framework/Features/Navigation/DocumentationSidebar.php b/packages/framework/src/Framework/Features/Navigation/DocumentationSidebar.php index 2808fccf51d..b9eeccf4e05 100644 --- a/packages/framework/src/Framework/Features/Navigation/DocumentationSidebar.php +++ b/packages/framework/src/Framework/Features/Navigation/DocumentationSidebar.php @@ -53,8 +53,9 @@ public function getItemsInGroup(?string $group): Collection public function isGroupActive(string $group): bool { - return Hyde::makeSlug(Render::getPage()->navigationMenuGroup()) === $group - || $this->isPageIndexPage() && $this->shouldIndexPageBeActive($group); + $normalized = Hyde::makeSlug(Render::getPage()->navigationMenuGroup()); + + return ($normalized === $group) || ($this->isPageIndexPage() && $this->shouldIndexPageBeActive($group)); } public function makeGroupTitle(string $group): string From 48213a376eeebea0801dac6a58bff8574d7ba92d Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sun, 22 Dec 2024 10:19:23 +0100 Subject: [PATCH 07/12] Add comparison fallback instead of null value --- .../src/Framework/Features/Navigation/DocumentationSidebar.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/framework/src/Framework/Features/Navigation/DocumentationSidebar.php b/packages/framework/src/Framework/Features/Navigation/DocumentationSidebar.php index b9eeccf4e05..f9fc088a82f 100644 --- a/packages/framework/src/Framework/Features/Navigation/DocumentationSidebar.php +++ b/packages/framework/src/Framework/Features/Navigation/DocumentationSidebar.php @@ -53,7 +53,7 @@ public function getItemsInGroup(?string $group): Collection public function isGroupActive(string $group): bool { - $normalized = Hyde::makeSlug(Render::getPage()->navigationMenuGroup()); + $normalized = Hyde::makeSlug(Render::getPage()->navigationMenuGroup() ?? 'other'); return ($normalized === $group) || ($this->isPageIndexPage() && $this->shouldIndexPageBeActive($group)); } From 586492a5cb0315cbc6aeb4662ffeff189062fd7d Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sun, 22 Dec 2024 10:19:37 +0100 Subject: [PATCH 08/12] Regenerate documentation for added method --- .../hyde-pages-api/hyde-kernel-string-methods.md | 10 +++++++++- docs/architecture-concepts/the-hydekernel.md | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/docs/_data/partials/hyde-pages-api/hyde-kernel-string-methods.md b/docs/_data/partials/hyde-pages-api/hyde-kernel-string-methods.md index 4659a1ed2f2..60c1f74ed80 100644 --- a/docs/_data/partials/hyde-pages-api/hyde-kernel-string-methods.md +++ b/docs/_data/partials/hyde-pages-api/hyde-kernel-string-methods.md @@ -1,7 +1,7 @@
- + #### `makeTitle()` @@ -11,6 +11,14 @@ No description provided. Hyde::makeTitle(string $value): string ``` +#### `makeSlug()` + +No description provided. + +```php +Hyde::makeSlug(string $value): string +``` + #### `normalizeNewlines()` No description provided. diff --git a/docs/architecture-concepts/the-hydekernel.md b/docs/architecture-concepts/the-hydekernel.md index 9f470ed3835..e7cd81eecb4 100644 --- a/docs/architecture-concepts/the-hydekernel.md +++ b/docs/architecture-concepts/the-hydekernel.md @@ -140,7 +140,7 @@ Hyde::routes(): Hyde\Foundation\Kernel\RouteCollection
- + #### `makeTitle()` @@ -150,6 +150,14 @@ No description provided. Hyde::makeTitle(string $value): string ``` +#### `makeSlug()` + +No description provided. + +```php +Hyde::makeSlug(string $value): string +``` + #### `normalizeNewlines()` No description provided. From 011d4a0788e34ae6d84b26b0c76ea550bde25a79 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sun, 22 Dec 2024 11:40:44 +0100 Subject: [PATCH 09/12] Add todo to match normalization to v2 generation Want to match https://github.com/hydephp/develop/pull/2059, but that would change output so deferring to v2. --- .../src/Foundation/Concerns/ImplementsStringHelpers.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/framework/src/Foundation/Concerns/ImplementsStringHelpers.php b/packages/framework/src/Foundation/Concerns/ImplementsStringHelpers.php index f95dc622fb3..910960488a2 100644 --- a/packages/framework/src/Foundation/Concerns/ImplementsStringHelpers.php +++ b/packages/framework/src/Foundation/Concerns/ImplementsStringHelpers.php @@ -46,6 +46,8 @@ public static function makeSlug(string $value): string // Transliterate international characters to ASCII $value = Str::transliterate($value); + // Todo: In v2.0 we will use the following dictionary: ['@' => 'at', '&' => 'and'] + return Str::slug($value); } From 7f2ae3c584d717b28d1d8b25a153d3e240647186 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sun, 22 Dec 2024 11:54:22 +0100 Subject: [PATCH 10/12] Create high level internationalization test --- .../Feature/InternationalizationTest.php | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 packages/framework/tests/Feature/InternationalizationTest.php diff --git a/packages/framework/tests/Feature/InternationalizationTest.php b/packages/framework/tests/Feature/InternationalizationTest.php new file mode 100644 index 00000000000..75738b2877c --- /dev/null +++ b/packages/framework/tests/Feature/InternationalizationTest.php @@ -0,0 +1,70 @@ +save(); + + $this->assertSame('_posts/ni-hao-shi-jie.md', $path); + $this->assertSame('ni-hao-shi-jie', $creator->getIdentifier()); + $this->assertSame($creator->getIdentifier(), Hyde::makeSlug('你好世界')); + $this->assertFileExists($path); + + $contents = file_get_contents($path); + $this->assertStringContainsString('title: 你好世界', $contents); + $this->assertSame(<<<'EOF' + --- + title: 你好世界 + description: 简短描述 + category: blog + author: default + date: '2024-12-22 10:45' + --- + + ## Write something awesome. + + EOF, $contents); + + Filesystem::unlink($path); + } + + public function testCanCompileBlogPostFilesWithInternationalCharacterSets() + { + $page = new MarkdownPost('ni-hao-shi-jie', [ + 'title' => '你好世界', + 'description' => '简短描述', + 'category' => 'blog', + 'author' => 'default', + 'date' => '2024-12-22 10:45', + ]); + + $path = StaticPageBuilder::handle($page); + + $this->assertSame(Hyde::path('_site/posts/ni-hao-shi-jie.html'), $path); + $this->assertFileExists($path); + + $contents = file_get_contents($path); + + $this->assertStringContainsString('HydePHP - 你好世界', $contents); + $this->assertStringContainsString('

你好世界

', $contents); + $this->assertStringContainsString('', $contents); + + Filesystem::unlink($path); + } +} From 51d4198605e81b379968103e1616587ab83dc34c Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sun, 22 Dec 2024 12:04:12 +0100 Subject: [PATCH 11/12] Use data provider to test more character sets --- .../Feature/InternationalizationTest.php | 85 ++++++++++++++----- 1 file changed, 66 insertions(+), 19 deletions(-) diff --git a/packages/framework/tests/Feature/InternationalizationTest.php b/packages/framework/tests/Feature/InternationalizationTest.php index 75738b2877c..04e6d6fa861 100644 --- a/packages/framework/tests/Feature/InternationalizationTest.php +++ b/packages/framework/tests/Feature/InternationalizationTest.php @@ -16,22 +16,38 @@ */ class InternationalizationTest extends TestCase { - public function testCanCreateBlogPostFilesWithInternationalCharacterSets() - { - $creator = new CreatesNewMarkdownPostFile('你好世界', '简短描述', 'blog', 'default', '2024-12-22 10:45'); + /** + * @dataProvider internationalCharacterSetsProvider + */ + public function testCanCreateBlogPostFilesWithInternationalCharacterSets( + string $title, + string $description, + string $expectedSlug, + string $expectedTitle + ) { + $creator = new CreatesNewMarkdownPostFile($title, $description, 'blog', 'default', '2024-12-22 10:45'); $path = $creator->save(); - $this->assertSame('_posts/ni-hao-shi-jie.md', $path); - $this->assertSame('ni-hao-shi-jie', $creator->getIdentifier()); - $this->assertSame($creator->getIdentifier(), Hyde::makeSlug('你好世界')); + $this->assertSame("_posts/$expectedSlug.md", $path); + $this->assertSame($expectedSlug, $creator->getIdentifier()); + $this->assertSame($creator->getIdentifier(), Hyde::makeSlug($title)); $this->assertFileExists($path); $contents = file_get_contents($path); - $this->assertStringContainsString('title: 你好世界', $contents); - $this->assertSame(<<<'EOF' + + if (str_contains($title, ' ')) { + $expectedTitle = "'$expectedTitle'"; + } + + if (str_contains($description, ' ')) { + $description = "'$description'"; + } + + $this->assertStringContainsString("title: $expectedTitle", $contents); + $this->assertSame(<< '你好世界', - 'description' => '简短描述', + /** + * @dataProvider internationalCharacterSetsProvider + */ + public function testCanCompileBlogPostFilesWithInternationalCharacterSets( + string $title, + string $description, + string $expectedSlug, + string $expectedTitle + ) { + $page = new MarkdownPost($expectedSlug, [ + 'title' => $title, + 'description' => $description, 'category' => 'blog', 'author' => 'default', 'date' => '2024-12-22 10:45', @@ -56,15 +79,39 @@ public function testCanCompileBlogPostFilesWithInternationalCharacterSets() $path = StaticPageBuilder::handle($page); - $this->assertSame(Hyde::path('_site/posts/ni-hao-shi-jie.html'), $path); + $this->assertSame(Hyde::path("_site/posts/$expectedSlug.html"), $path); $this->assertFileExists($path); $contents = file_get_contents($path); - $this->assertStringContainsString('HydePHP - 你好世界', $contents); - $this->assertStringContainsString('

你好世界

', $contents); - $this->assertStringContainsString('', $contents); + $this->assertStringContainsString("HydePHP - $expectedTitle", $contents); + $this->assertStringContainsString("

$expectedTitle

", $contents); + $this->assertStringContainsString("", $contents); Filesystem::unlink($path); } + + public static function internationalCharacterSetsProvider(): array + { + return [ + 'Chinese (Simplified)' => [ + '你好世界', + '简短描述', + 'ni-hao-shi-jie', + '你好世界', + ], + 'Japanese' => [ + 'こんにちは世界', + '短い説明', + 'konnichihashi-jie', + 'こんにちは世界', + ], + 'Korean' => [ + '안녕하세요 세계', + '짧은 설명', + 'annyeonghaseyo-segye', + '안녕하세요 세계', + ], + ]; + } } From 829f0e46637a84a5fceb36787ac6d2e422631d75 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sun, 22 Dec 2024 12:00:28 +0100 Subject: [PATCH 12/12] Update RELEASE_NOTES.md --- RELEASE_NOTES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index d0222bf5e85..9300bb0087a 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -16,6 +16,7 @@ This serves two purposes: - All page types now support the `description` front matter field (used in page metadata) in https://github.com/hydephp/develop/pull/1884 - Added a new `Filesystem::findFiles()` method to find files in a directory in https://github.com/hydephp/develop/pull/2064 - Added `webp` to the list of default media extensions in https://github.com/hydephp/framework/pull/663 +- Added a new slug generation helper to improve internationalization support in https://github.com/hydephp/develop/pull/2070 ### Changed - Changed the `Hyde` facade to use a `@mixin` annotation instead of single method annotations in https://github.com/hydephp/develop/pull/1919 @@ -26,6 +27,7 @@ This serves two purposes: - The `torchlight:install` command is now hidden from the command list as it's already installed in https://github.com/hydephp/develop/pull/1879 - Updated the home page fallback link in the 404 template to lead to the site root in https://github.com/hydephp/develop/pull/1880 (fixes https://github.com/hydephp/develop/issues/1781) - Normalized remote URL checks so that protocol relative URLs `//` are consistently considered to be remote in all places in https://github.com/hydephp/develop/pull/1882 (fixes https://github.com/hydephp/develop/issues/1788) +- Page slugs are now generated using our automatically internationalizing slug generator to transliterate input to ASCII in https://github.com/hydephp/develop/pull/2070 - Replaced internal usages of glob functions with our improved file finder in https://github.com/hydephp/develop/pull/2064 - Updated to HydeFront v3.4 in https://github.com/hydephp/develop/pull/1803 - Realtime Compiler: Virtual routes are now managed through the service container in https://github.com/hydephp/develop/pull/1858 @@ -46,6 +48,7 @@ This serves two purposes: - Fixed heading permalinks button text showing in Google Search previews https://github.com/hydephp/develop/issues/1801 in https://github.com/hydephp/develop/pull/1803 - Fixed routing issues with nested 404 pages where an index page does not exist https://github.com/hydephp/develop/issues/1781 in https://github.com/hydephp/develop/pull/1880 - Fixed URL metadata for blog posts not using customized post output directories in https://github.com/hydephp/develop/pull/1889 +- Fixed lacking support for logographic slug generation https://github.com/hydephp/hyde/issues/269 in https://github.com/hydephp/develop/pull/2070 - Improved printed documentation views in https://github.com/hydephp/develop/pull/2005 - Fixed "BuildService finding non-existent files to copy in Debian" https://github.com/hydephp/framework/issues/662 in https://github.com/hydephp/develop/pull/2064 - Fixed "Undefined constant `Hyde\Foundation\Kernel\GLOB_BRACE`" https://github.com/hydephp/hyde/issues/270 in https://github.com/hydephp/develop/pull/2064