From cd7421f4274e73da1ab744a121e08a8df2d338e2 Mon Sep 17 00:00:00 2001 From: Jason McCreary Date: Fri, 14 Nov 2025 05:40:01 +1000 Subject: [PATCH] Register custom shorthands --- src/Blueprint.php | 73 ++++++++++++++++++++------------- tests/Feature/BlueprintTest.php | 22 ++++++++++ 2 files changed, 66 insertions(+), 29 deletions(-) diff --git a/src/Blueprint.php b/src/Blueprint.php index 3d2f916a..615b5629 100644 --- a/src/Blueprint.php +++ b/src/Blueprint.php @@ -13,41 +13,17 @@ class Blueprint private array $generators = []; - public static function relativeNamespace(string $fullyQualifiedClassName): string - { - $namespace = config('blueprint.namespace') . '\\'; - $reference = ltrim($fullyQualifiedClassName, '\\'); - - if (Str::startsWith($reference, $namespace)) { - return Str::after($reference, $namespace); - } + private array $shorthands = []; - return $reference; - } - - public static function appPath() + public function registerShorthand(string $shorthand, \Closure $callback): void { - return str_replace('\\', '/', config('blueprint.app_path')); + $this->shorthands[$shorthand] = $callback; } - public function parse($content, $strip_dashes = true) + private function expandShorthands(string $content): string { - $content = str_replace(["\r\n", "\r"], "\n", $content); - - if ($strip_dashes) { - $content = preg_replace('/^(\s*)-\s*/m', '\1', $content); - } - - $content = $this->transformDuplicatePropertyKeys($content); - $content = preg_replace_callback( - '/^(\s+)(id|timestamps(Tz)?|softDeletes(Tz)?)$/mi', - fn ($matches) => $matches[1] . strtolower($matches[2]) . ': ' . $matches[2], - $content - ); - - $content = preg_replace_callback( - '/^(\s+)(id|timestamps(Tz)?|softDeletes(Tz)?): true$/mi', + '/^(\s+)(id|timestamps(Tz)?|softDeletes(Tz)?)(: true)?$/mi', fn ($matches) => $matches[1] . strtolower($matches[2]) . ': ' . $matches[2], $content ); @@ -70,6 +46,45 @@ public function parse($content, $strip_dashes = true) $content ); + foreach ($this->shorthands as $shorthand => $callback) { + $content = preg_replace_callback( + '/^(\s+)' . preg_quote($shorthand, '/') . '$/mi', + $callback, + $content + ); + } + + return $content; + } + + public static function relativeNamespace(string $fullyQualifiedClassName): string + { + $namespace = config('blueprint.namespace') . '\\'; + $reference = ltrim($fullyQualifiedClassName, '\\'); + + if (Str::startsWith($reference, $namespace)) { + return Str::after($reference, $namespace); + } + + return $reference; + } + + public static function appPath() + { + return str_replace('\\', '/', config('blueprint.app_path')); + } + + public function parse($content, $strip_dashes = true) + { + $content = str_replace(["\r\n", "\r"], "\n", $content); + + if ($strip_dashes) { + $content = preg_replace('/^(\s*)-\s*/m', '\1', $content); + } + + $content = $this->transformDuplicatePropertyKeys($content); + $content = $this->expandShorthands($content); + return Yaml::parse($content); } diff --git a/tests/Feature/BlueprintTest.php b/tests/Feature/BlueprintTest.php index 8cf9ca22..c7d17f6f 100644 --- a/tests/Feature/BlueprintTest.php +++ b/tests/Feature/BlueprintTest.php @@ -624,6 +624,28 @@ public function it_parses_uuid_shorthand(): void ], $this->subject->parse($blueprint)); } + #[Test] + public function it_replaces_custom_shorthands(): void + { + $this->subject->registerShorthand('custom', fn ($matches) => $matches[1] . 'custom: shorthand'); + + $blueprint = <<<'DRAFT' +models: + Person: + custom + another: custom +DRAFT; + + $this->assertEquals([ + 'models' => [ + 'Person' => [ + 'custom' => 'shorthand', + 'another' => 'custom', + ], + ], + ], $this->subject->parse($blueprint)); + } + #[Test] public function it_parses_yaml_with_dashed_syntax(): void {