Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ See the [PlaceholderFormatter documentation](docs/PlaceholderFormatter.md) and [
| [PatternFormatter](docs/PatternFormatter.md) | Pattern-based string filtering with placeholders |
| [PlaceholderFormatter](docs/PlaceholderFormatter.md) | Template interpolation with placeholder replacement |
| [TimeFormatter](docs/TimeFormatter.md) | Time promotion (mil, c, dec, y, mo, w, d, h, min, s, ms, us, ns) |
| [TrimFormatter](docs/TrimFormatter.md) | Remove whitespace from string edges |

## Contributing

Expand Down
145 changes: 145 additions & 0 deletions docs/TrimFormatter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<!--
SPDX-FileCopyrightText: (c) Respect Project Contributors
SPDX-License-Identifier: ISC
SPDX-FileContributor: Henrique Moody <henriquemoody@gmail.com>
-->

# TrimFormatter

The `TrimFormatter` removes characters from the edges of strings with configurable masking and side selection, fully supporting UTF-8 Unicode characters.

## Usage

### Basic Usage

```php
use Respect\StringFormatter\TrimFormatter;

$formatter = new TrimFormatter();

echo $formatter->format(' hello world ');
// Outputs: "hello world"
```

### Trim Specific Side

```php
use Respect\StringFormatter\TrimFormatter;

$formatter = new TrimFormatter('left');

echo $formatter->format(' hello ');
// Outputs: "hello "

$formatterRight = new TrimFormatter('right');

echo $formatterRight->format(' hello ');
// Outputs: " hello"
```

### Custom Mask

```php
use Respect\StringFormatter\TrimFormatter;

$formatter = new TrimFormatter('both', '-._');

echo $formatter->format('---hello---');
// Outputs: "hello"

echo $formatter->format('._hello_._');
// Outputs: "hello"
```

### Unicode Characters

```php
use Respect\StringFormatter\TrimFormatter;

// CJK full-width spaces are trimmed by default
$formatter = new TrimFormatter();

echo $formatter->format(' hello世界 ');
// Outputs: "hello世界"

// Trim emoji with custom mask
$formatterEmoji = new TrimFormatter('both', '😊');

echo $formatterEmoji->format('😊hello😊');
// Outputs: "hello"
```

## API

### `TrimFormatter::__construct`

- `__construct(string $side = "both", string|null $mask = null)`

Creates a new trim formatter instance.

**Parameters:**

- `$side`: Which side(s) to trim: "left", "right", or "both" (default: "both")
- `$mask`: The characters to trim from the string edges, or `null` for default Unicode whitespace (default: `null`)

**Throws:** `InvalidFormatterException` when `$side` is not "left", "right", or "both"

### `format`

- `format(string $input): string`

Removes characters from the specified side(s) of the input string.

**Parameters:**

- `$input`: The string to trim

**Returns:** The trimmed string

## Examples

| Side | Mask | Input | Output | Description |
| --------- | -------------- | --------------- | ------------ | ----------------------------------- |
| `"both"` | `null` | `" hello "` | `"hello"` | Trim default whitespace both sides |
| `"left"` | `null` | `" hello "` | `"hello "` | Trim default whitespace left only |
| `"right"` | `null` | `" hello "` | `" hello"` | Trim default whitespace right only |
| `"both"` | `"-"` | `"---hello---"` | `"hello"` | Trim hyphens from both sides |
| `"both"` | `"-._"` | `"-._hello_.-"` | `"hello"` | Trim multiple custom characters |
| `"left"` | `":"` | `":::hello:::"` | `"hello:::"` | Trim colons from left only |
| `"both"` | `null` | `" hello"` | `"hello"` | CJK space trimmed by default |
| `"both"` | `"😊"` | `"😊hello😊"` | `"hello"` | Trim emoji with custom mask |

## Notes

- Uses PHP's `mb_trim`, `mb_ltrim`, and `mb_rtrim` functions for multibyte-safe trimming
- Fully UTF-8 aware - handles all Unicode scripts including CJK, emoji, and complex characters
- Empty strings return empty strings
- If the mask is empty or contains no characters present in the input, the string is returned unchanged
- Trimming operations are character-oriented, not byte-oriented

### Default Mask

When no mask is provided (`null`), the formatter uses `mb_trim`'s default which includes all Unicode whitespace characters:

**ASCII whitespace:**
- ` ` (U+0020): Ordinary space
- `\t` (U+0009): Tab
- `\n` (U+000A): New line (line feed)
- `\r` (U+000D): Carriage return
- `\0` (U+0000): NUL-byte
- `\v` (U+000B): Vertical tab
- `\f` (U+000C): Form feed

**Unicode whitespace:**
- U+00A0: No-break space
- U+1680: Ogham space mark
- U+2000–U+200A: Various width spaces (en quad, em quad, en space, em space, etc.)
- U+2028: Line separator
- U+2029: Paragraph separator
- U+202F: Narrow no-break space
- U+205F: Medium mathematical space
- U+3000: Ideographic space (CJK full-width space)
- U+0085: Next line (NEL)
- U+180E: Mongolian vowel separator

See [mb_trim documentation](https://www.php.net/manual/en/function.mb-trim.php) for the complete list.
11 changes: 7 additions & 4 deletions src/Mixin/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,33 @@ interface Builder
{
public static function area(string $unit): FormatterBuilder;

public static function date(string $format = 'Y-m-d H:i:s'): FormatterBuilder;

public static function imperialArea(string $unit): FormatterBuilder;

public static function imperialLength(string $unit): FormatterBuilder;

public static function imperialMass(string $unit): FormatterBuilder;

public static function date(string $format = 'Y-m-d H:i:s'): FormatterBuilder;

public static function mask(string $range, string $replacement = '*'): FormatterBuilder;

public static function metric(string $unit): FormatterBuilder;

public static function metricMass(string $unit): FormatterBuilder;

public static function number(
int $decimals = 0,
string $decimalSeparator = '.',
string $thousandsSeparator = ',',
): FormatterBuilder;

public static function metricMass(string $unit): FormatterBuilder;

public static function pattern(string $pattern): FormatterBuilder;

/** @param array<string, mixed> $parameters */
public static function placeholder(array $parameters): FormatterBuilder;

public static function time(string $unit): FormatterBuilder;

/** @param 'both'|'left'|'right' $side */
public static function trim(string $side = 'both', string $mask = " \t\n\r\0\x0B"): FormatterBuilder;
}
11 changes: 7 additions & 4 deletions src/Mixin/Chain.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,33 @@ interface Chain extends Formatter
{
public function area(string $unit): FormatterBuilder;

public function date(string $format = 'Y-m-d H:i:s'): FormatterBuilder;

public function imperialArea(string $unit): FormatterBuilder;

public function imperialLength(string $unit): FormatterBuilder;

public function imperialMass(string $unit): FormatterBuilder;

public function date(string $format = 'Y-m-d H:i:s'): FormatterBuilder;

public function mask(string $range, string $replacement = '*'): FormatterBuilder;

public function metric(string $unit): FormatterBuilder;

public function metricMass(string $unit): FormatterBuilder;

public function number(
int $decimals = 0,
string $decimalSeparator = '.',
string $thousandsSeparator = ',',
): FormatterBuilder;

public function metricMass(string $unit): FormatterBuilder;

public function pattern(string $pattern): FormatterBuilder;

/** @param array<string, mixed> $parameters */
public function placeholder(array $parameters): FormatterBuilder;

public function time(string $unit): FormatterBuilder;

/** @param 'both'|'left'|'right' $side */
public function trim(string $side = 'both', string $mask = " \t\n\r\0\x0B"): FormatterBuilder;
}
53 changes: 53 additions & 0 deletions src/TrimFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

/*
* SPDX-FileCopyrightText: (c) Respect Project Contributors
* SPDX-License-Identifier: ISC
* SPDX-FileContributor: Henrique Moody <henriquemoody@gmail.com>
*/

declare(strict_types=1);

namespace Respect\StringFormatter;

use function in_array;
use function mb_ltrim;
use function mb_rtrim;
use function mb_trim;
use function sprintf;

/**
* Trims characters from strings using multibyte-safe functions.
*
* When no mask is provided, trims all Unicode whitespace characters including:
* regular space, tab, newline, carriage return, vertical tab, form feed,
* no-break space (U+00A0), em space (U+2003), ideographic space (U+3000), and others.
*
* @see https://www.php.net/manual/en/function.mb-trim.php
*/
final readonly class TrimFormatter implements Formatter
{
/**
* @param 'both'|'left'|'right' $side Which side(s) to trim
* @param string|null $mask Characters to trim, or null for default Unicode whitespace
*/
public function __construct(
private string $side = 'both',
private string|null $mask = null,
) {
if (!in_array($this->side, ['left', 'right', 'both'], true)) {
throw new InvalidFormatterException(
sprintf('Invalid side "%s". Must be "left", "right", or "both".', $this->side),
);
}
}

public function format(string $input): string
{
return match ($this->side) {
'left' => mb_ltrim($input, $this->mask),
'right' => mb_rtrim($input, $this->mask),
default => mb_trim($input, $this->mask),
};
}
}
Loading