diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php index f36d2d3..72dd165 100644 --- a/src/ServiceProvider.php +++ b/src/ServiceProvider.php @@ -30,11 +30,11 @@ public function register() */ public function boot() { - Str::macro('typography', function (string $value) { - return (new Typography($value))->handle(); + Str::macro('typography', function (string $value, null|string|array $only = null, null|string|array $except = null) { + return (new Typography($value))->handle(only: $only, except: $except); }); - Stringable::macro('typography', function () { - return new static(Str::typography($this->value)); + Stringable::macro('typography', function (null|string|array $only = null, null|string|array $except = null) { + return new static(Str::typography($this->value, $only, $except)); }); } } diff --git a/src/Typography.php b/src/Typography.php index bee34a5..d5aa5e9 100644 --- a/src/Typography.php +++ b/src/Typography.php @@ -35,11 +35,20 @@ static public function remove(string $key): void } /** - * Remove a typographic rule handler. + * Return the requested handlers. */ - static protected function getHandlers(): array + static protected function getHandlers(null|string|array $only = null, null|string|array $except = null): array { - return array_reduce(static::$handlers, function($all, $handler) { + $only = ($only ? (is_array($only) ? $only : [$only]) : null); + $except = ($except ? (is_array($except) ? $except : [$except]) : null); + + $handlers = match (true) { + !is_null($only) => array_filter(static::$handlers, fn($key) => in_array($key, $only), ARRAY_FILTER_USE_KEY), + !is_null($except) => array_filter(static::$handlers, fn($key) => !in_array($key, $except), ARRAY_FILTER_USE_KEY), + default => static::$handlers, + }; + + return array_reduce($handlers, function($all, $handler) { [$regex, $callback] = $handler; $all[$regex] = $callback; return $all; @@ -57,10 +66,10 @@ public function __construct(string $value) /** * Run the value transformations. */ - public function handle(): string + public function handle(null|string|array $only = null, null|string|array $except = null): string { return preg_replace_callback_array( - static::getHandlers(), + static::getHandlers(only: $only, except: $except), $this->value ); } diff --git a/tests/Feature/TypographyTest.php b/tests/Feature/TypographyTest.php index 3b150a7..38d6cd3 100644 --- a/tests/Feature/TypographyTest.php +++ b/tests/Feature/TypographyTest.php @@ -49,9 +49,55 @@ callback: fn(array $matches) => 'b', ); - expect((string) str('...Banana !')->typography())->toBe('…Bbnbnb !'); + expect((string) str('...Banana !')->typography()) + ->toBe('…Bbnbnb !'); Typography::remove('a-to-b'); - expect((string) str('...Banana !')->typography())->toBe('…Banana !'); + expect((string) str('...Banana !')->typography()) + ->toBe('…Banana !'); +}); + +it('can execute one of the declared rules', function() { + expect((string) str('...Banana !')->typography(only: 'hellip')) + ->toBe('…Banana !'); +}); + +it('can execute some of the declared rules', function() { + Typography::rule( + key: 'a-to-b', + regex: '/a/', + callback: fn(array $matches) => 'b', + ); + + expect((string) str('...Banana !')->typography(only: ['hellip','unbreakable-punctuation'])) + ->toBe('…Banana !'); + + Typography::remove('a-to-b'); +}); + +it('can execute all of the declared rules except one', function() { + Typography::rule( + key: 'a-to-b', + regex: '/a/', + callback: fn(array $matches) => 'b', + ); + + expect((string) str('...Banana !')->typography(except: 'hellip')) + ->toBe('...Bbnbnb !'); + + Typography::remove('a-to-b'); +}); + +it('can execute all of the declared rules except some', function() { + Typography::rule( + key: 'a-to-b', + regex: '/a/', + callback: fn(array $matches) => 'b', + ); + + expect((string) str('...Banana !')->typography(except: ['hellip','unbreakable-punctuation'])) + ->toBe('...Bbnbnb !'); + + Typography::remove('a-to-b'); });