diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..2cc8ff4
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,30 @@
+name: CI
+
+on:
+ push:
+ branches: [master]
+ pull_request:
+ branches: [master]
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+
+ strategy:
+ matrix:
+ php-version: ['8.2', '8.3', '8.4']
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Set up PHP ${{ matrix.php-version }}
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php-version }}
+ extensions: mbstring
+
+ - name: Install dependencies
+ run: composer install --no-interaction --prefer-dist
+
+ - name: Run tests
+ run: vendor/bin/phpunit --testdox
diff --git a/.gitignore b/.gitignore
index dccb98d..61fb2a7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
/.idea
/composer.lock
/vendor
+/.phpunit.cache
.DS_Store
diff --git a/README.md b/README.md
index 083d4ca..0b3ffdc 100644
--- a/README.md
+++ b/README.md
@@ -1,34 +1,54 @@
-# Strip accents
-This PHP 7 library removes accent from strings. It is based on the sample code [published here](http://www.infowebmaster.fr/tutoriel/php-enlever-accents).
+# Strip Accents
+[](https://packagist.org/packages/codeinc/strip-accents)
+[](https://packagist.org/packages/codeinc/strip-accents)
+[](https://packagist.org/packages/codeinc/strip-accents)
+[](LICENSE)
+
+A PHP library to remove accents and diacritics from strings.
+
+## Installation
+
+```bash
+composer require codeinc/strip-accents
+```
+
+Requires PHP 8.2 or later with the `mbstring` extension.
+
+## Usage
+
+### Strip accents
-## Usage
```php
-=7.1"
+ "php": ">=8.2",
+ "ext-mbstring": "*"
},
"require-dev": {
- "phpunit/phpunit": "^7"
+ "phpunit/phpunit": "^11.0"
},
"autoload": {
"psr-4": {
@@ -34,4 +34,4 @@
"*": "dist"
}
}
-}
\ No newline at end of file
+}
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
new file mode 100644
index 0000000..68b052b
--- /dev/null
+++ b/phpunit.xml.dist
@@ -0,0 +1,17 @@
+
+
+
+
+ tests
+
+
+
+
+ src
+
+
+
diff --git a/src/StripAccents.php b/src/StripAccents.php
index 220a023..9d73bf9 100644
--- a/src/StripAccents.php
+++ b/src/StripAccents.php
@@ -1,77 +1,48 @@
-// Date: 15/03/2018
-// Time: 10:52
-// Project: StipAccents
-//
-declare(strict_types = 1);
-namespace CodeInc\StripAccents;
+declare(strict_types=1);
+
+namespace CodeInc\StripAccents;
/**
- * Class StripAccents
- *
- * @link http://www.infowebmaster.fr/tutoriel/php-enlever-accents
- * @package CodeInc\StripAccents
- * @author Joan Fabrégat
+ * Removes accents and diacritics from strings.
*/
class StripAccents
{
public const DEFAULT_ENCODING = 'utf-8';
/**
- * @param string $string
- * @param string $encoding
- * @return string
+ * Strips accents and diacritics from a string.
*/
public static function strip(string $string, string $encoding = self::DEFAULT_ENCODING): string
{
- // converting accents in HTML entities
$string = htmlentities($string, ENT_NOQUOTES, $encoding);
- // replacing the HTML entities to extract the first letter
- // examples: "&ecute;" => "e", "&Ecute;" => "E", "à" => "a" ...
+ // replace accented HTML entities with their base letter
+ // e.g. "é" => "e", "É" => "E", "à" => "a"
$string = preg_replace(
- '#&([A-za-z])(?:acute|grave|cedil|circ|orn|ring|slash|th|tilde|uml);#',
+ '#&([A-Za-z])(?:acute|grave|cedil|circ|orn|ring|slash|th|tilde|uml);#',
'\1',
$string
);
- // replacing ligatures
- // Exemple "œ" => "oe", "Æ" => "AE"
- $string = preg_replace('#&([A-za-z]{2})(?:lig);#', '\1', $string);
+ // replace ligatures e.g. "œ" => "oe", "Æ" => "AE"
+ $string = preg_replace('#&([A-Za-z]{2})(?:lig);#', '\1', $string);
- // removing the remaining bits
+ // remove any remaining HTML entities
$string = preg_replace('#&[^;]+;#', '', $string);
return $string;
}
/**
- * @param string $string
- * @param string $encoding
- * @param string $replaceWith
- * @return string
+ * Strips accents and non-printable characters from a string.
*/
- public static function stripNonPrint(string $string,
- string $replaceWith = '',
- string $encoding = self::DEFAULT_ENCODING): string
- {
+ public static function stripNonPrint(
+ string $string,
+ string $replaceWith = '',
+ string $encoding = self::DEFAULT_ENCODING,
+ ): string {
return preg_replace('/[[:^print:]]/', $replaceWith, self::strip($string, $encoding));
}
-}
\ No newline at end of file
+}
diff --git a/tests/StripAccentsTest.php b/tests/StripAccentsTest.php
index 59650ef..e3471fc 100644
--- a/tests/StripAccentsTest.php
+++ b/tests/StripAccentsTest.php
@@ -1,63 +1,93 @@
-// Date: 15/03/2018
-// Time: 10:57
-// Project: StripAccents
-//
-declare(strict_types = 1);
+
+declare(strict_types=1);
+
namespace CodeInc\StripAccents\Tests;
+
use CodeInc\StripAccents\StripAccents;
+use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
-
-/**
- * Class StripAccentsTest
- *
- * @package CodeInc\StripAccents\Tests
- * @author Joan Fabrégat
- */
class StripAccentsTest extends TestCase
{
- public const ACCENTS = [
- 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î',
- 'Ï', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'à', 'á', 'â',
- 'ã', 'ä', 'å', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ð', 'ò',
- 'ó', 'ô', 'õ', 'ö', 'ù', 'ú', 'û', 'ü', 'ý', 'ÿ'];
-
- public const LETTERS = [
- 'A', 'A', 'A', 'A', 'A', 'A', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I',
- 'I', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y', 'a', 'a', 'a',
- 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'e', 'o',
- 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'y'
+ private const ACCENT_MAP = [
+ 'À' => 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'A', 'Å' => 'A',
+ 'Ç' => 'C',
+ 'È' => 'E', 'É' => 'E', 'Ê' => 'E', 'Ë' => 'E',
+ 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I', 'Ï' => 'I',
+ 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O', 'Õ' => 'O', 'Ö' => 'O',
+ 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'U',
+ 'Ý' => 'Y',
+ 'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' => 'a', 'å' => 'a',
+ 'ç' => 'c',
+ 'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e',
+ 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i',
+ 'ð' => 'e',
+ 'ò' => 'o', 'ó' => 'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'o',
+ 'ù' => 'u', 'ú' => 'u', 'û' => 'u', 'ü' => 'u',
+ 'ý' => 'y', 'ÿ' => 'y',
];
- public function testOneByOne():void
+ public static function accentProvider(): iterable
{
- foreach (self::ACCENTS as $key => $accent) {
- self::assertTrue(StripAccents::strip($accent) == self::LETTERS[$key]);
+ foreach (self::ACCENT_MAP as $accented => $expected) {
+ yield $accented => [$accented, $expected];
}
}
- public function testAll():void
+ #[DataProvider('accentProvider')]
+ public function testIndividualAccent(string $accented, string $expected): void
+ {
+ $this->assertSame($expected, StripAccents::strip($accented));
+ }
+
+ public function testAllAccentsConcatenated(): void
{
- self::assertTrue(
- StripAccents::strip(implode("", self::ACCENTS))
- == implode(self::LETTERS)
+ $input = implode('', array_keys(self::ACCENT_MAP));
+ $expected = implode('', array_values(self::ACCENT_MAP));
+ $this->assertSame($expected, StripAccents::strip($input));
+ }
+
+ public function testSentence(): void
+ {
+ $this->assertSame(
+ "C'est une super chaine de caracteres avec beaucoup d'accents",
+ StripAccents::strip("C'est une super chaîne de caractères avec beaucoup d'accents"),
);
}
-}
\ No newline at end of file
+
+ public function testAsciiPassthrough(): void
+ {
+ $ascii = 'Hello World 123 !@#';
+ $this->assertSame($ascii, StripAccents::strip($ascii));
+ }
+
+ public function testEmptyString(): void
+ {
+ $this->assertSame('', StripAccents::strip(''));
+ }
+
+ public function testLigatures(): void
+ {
+ $this->assertSame('oe', StripAccents::strip('œ'));
+ $this->assertSame('AE', StripAccents::strip('Æ'));
+ }
+
+ public function testStripNonPrint(): void
+ {
+ $this->assertSame('ABC AEY ', StripAccents::stripNonPrint("ABC ÀÈÝ 是我这"));
+ }
+
+ public function testStripNonPrintWithReplacement(): void
+ {
+ $result = StripAccents::stripNonPrint("ABC ÀÈÝ 是我这", '-');
+ $this->assertStringStartsWith('ABC AEY ', $result);
+ // each CJK character is 3 bytes in UTF-8, each non-printable byte is replaced individually
+ $this->assertSame(9, substr_count($result, '-'));
+ }
+
+ public function testStripNonPrintEmptyString(): void
+ {
+ $this->assertSame('', StripAccents::stripNonPrint(''));
+ }
+}