From 651d090eae3a6c1468ff7674fdbb9c9df8a95a6c Mon Sep 17 00:00:00 2001 From: Emma De Silva Date: Thu, 1 Oct 2026 16:29:01 +0200 Subject: [PATCH 1/2] Only strip the leading base path when converting paths to relative The base path was removed with str_replace, so every later occurrence of it was stripped too. A project at /app serving /app/_media/app.css was reduced to _media.css, making the asset unresolvable. Co-Authored-By: Claude Opus 5 --- .../framework/src/Foundation/Kernel/Filesystem.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/framework/src/Foundation/Kernel/Filesystem.php b/packages/framework/src/Foundation/Kernel/Filesystem.php index 1c5c6730776..0f7cb8d1595 100644 --- a/packages/framework/src/Foundation/Kernel/Filesystem.php +++ b/packages/framework/src/Foundation/Kernel/Filesystem.php @@ -15,7 +15,8 @@ use function Hyde\normalize_slashes; use function Hyde\path_join; use function file_exists; -use function str_replace; +use function strlen; +use function substr; use function array_map; use function is_array; use function str_starts_with; @@ -90,8 +91,14 @@ public function pathToAbsolute(string|array $path): string|array */ public function pathToRelative(string $path): string { - return normalize_slashes(str_starts_with($path, $this->path()) - ? unslash(str_replace($this->path(), '', $path)) + $basePath = $this->path(); + + $isWithinBasePath = $path === $basePath + || str_starts_with($path, $basePath.'/') + || str_starts_with($path, $basePath.'\\'); + + return normalize_slashes($isWithinBasePath + ? unslash(substr($path, strlen($basePath))) : $path); } From 0500f0b523ad046803a86e9c0495699590a85503 Mon Sep 17 00:00:00 2001 From: Emma De Silva Date: Thu, 1 Oct 2026 16:29:07 +0200 Subject: [PATCH 2/2] Test base path prefix stripping boundaries Co-Authored-By: Claude Opus 5 --- .../Feature/Foundation/FilesystemTest.php | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/packages/framework/tests/Feature/Foundation/FilesystemTest.php b/packages/framework/tests/Feature/Foundation/FilesystemTest.php index 555156d4914..f9a17fda404 100644 --- a/packages/framework/tests/Feature/Foundation/FilesystemTest.php +++ b/packages/framework/tests/Feature/Foundation/FilesystemTest.php @@ -339,6 +339,28 @@ public function testPathToRelativeHelperDoesNotModifyAlreadyRelativePaths() $this->assertSame('foo/bar.md', Hyde::pathToRelative('foo/bar.md')); } + public function testPathToRelativeHelperOnlyStripsTheLeadingBasePath() + { + Hyde::getInstance()->setBasePath('/app'); + + $this->assertSame('_media/app.css', Hyde::pathToRelative('/app/_media/app.css')); + $this->assertSame('_media/app/app.css', Hyde::pathToRelative('/app/_media/app/app.css')); + } + + public function testPathToRelativeHelperDoesNotModifyPathsThatMerelyShareAPrefixWithTheBasePath() + { + Hyde::getInstance()->setBasePath('/app'); + + $this->assertSame('/applesauce/foo.css', Hyde::pathToRelative('/applesauce/foo.css')); + } + + public function testPathToRelativeHelperReturnsEmptyStringForTheBasePathItself() + { + Hyde::getInstance()->setBasePath('/app'); + + $this->assertSame('', Hyde::pathToRelative('/app')); + } + public function testPathToRelativeHelperDoesNotModifyNonProjectPaths() { $testStrings = [