PHPackages                             jolicode/jolitypo - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. jolicode/jolitypo

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

jolicode/jolitypo
=================

Microtypography fixer for the web.

v1.6.0(5mo ago)3471.1M↓19.6%27[3 PRs](https://github.com/jolicode/JoliTypo/pulls)5MITPHPPHP &gt;=8.1CI passing

Since Aug 22Pushed 5mo ago32 watchersCompare

[ Source](https://github.com/jolicode/JoliTypo)[ Packagist](https://packagist.org/packages/jolicode/jolitypo)[ Docs](https://github.com/jolicode/JoliTypo)[ RSS](/packages/jolicode-jolitypo/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (7)Versions (20)Used By (5)

 [![JoliTypo](https://camo.githubusercontent.com/87d4eeb5755771e425f4dcc3065e60a447348ccc27db8bb66835ba968ce92c9c/68747470733a2f2f6a6f6c69636f64652e636f6d2f6d656469612f6f726967696e616c2f6f73732f686561646572732f6a6f6c697479706f2e706e673f7633)](https://github.com/jolicode/JoliTypo)
 JoliTypo – Web Microtypography fixer
 *###### Finally a tool for typography nerds.*
===============================================================================================================================================================================================================================================================================================================================================================================

[](#------jolitypo--web-microtypography-fixer----finally-a-tool-for-typography-nerds)

[![PHP Version Require](https://camo.githubusercontent.com/1c5346c54773e11cf13bd26a75a72aaf5fcd3c02ee048f8f83fde0d0f147a22c/687474703a2f2f706f7365722e707567782e6f72672f6a6f6c69636f64652f6a6f6c697479706f2f726571756972652f706870)](https://packagist.org/packages/jolicode/jolitypo)[![Monthly Downloads](https://camo.githubusercontent.com/a95cacc7e450ccc5720a81c070a2c22ac25f9477f55dba2bd38e3251b98604dd/687474703a2f2f706f7365722e707567782e6f72672f6a6f6c69636f64652f6a6f6c697479706f2f642f6d6f6e74686c79)](https://packagist.org/packages/jolicode/jolitypo)

Introduction
============

[](#introduction)

JoliTypo is a tool fixing [Microtypography](https://en.wikipedia.org/wiki/Microtypography) glitches inside your HTML content. When your CMS outputs `" "` instead of `“ ”` or `...` instead of `…`, JoliTypo can help.

```
use JoliTypo\Fixer;

// Create a Fixer, specify the fixes
$fixer = new Fixer(['Ellipsis', 'Dash', 'SmartQuotes', 'CurlyQuote', 'Hyphen']);

// Get HTML content with correct microtypography
$fixedContent = $fixer->fix(
    '"Tell me Mr. Anderson... what good is a phone call... if you\'re unable to speak?" -- Agent Smith, Matrix.'
);
```

```
&ldquo;Tell me Mr. Ander&shy;son&hellip; what good is a phone call&hellip; if you&rsquo;re unable to speak?&rdquo;&mdash;Agent Smith, Matrix.
```

> “Tell me Mr. Anderson… what good is a phone call… if you’re unable to speak?”—Agent Smith, Matrix.

It's designed to be:

- language agnostic (you can fix `fr_FR`, `fr_CA`, `en_US`... you tell JoliTypo what to fix);
- easy to integrate into modern PHP projects (composer and autoload);
- robust (makes use of `\DOMDocument` instead of parsing HTML with dummy regexp);
- smart enough to avoid JavaScript, Code, CSS processing... (configurable protected tags list);
- fully tested;
- fully open and usable in any project (MIT License).

You can try it with the [online demo](https://jolitypo.jolicode.com/)!

Quick usage
===========

[](#quick-usage)

Just tell the Fixer class [which Fixer](#available-fixers) you want to run on your content and then, call `fix()`:

```
use JoliTypo\Fixer;

$fixer = new Fixer(['SmartQuotes', 'FrenchNoBreakSpace']);
$fixer->setLocale('fr_FR');

$fixedContent = $fixer->fix('Je suis "très content" de t\'avoir invité sur Jolicode.com !');
```

For your ease of use, you can find [ready to use list of Fixer for your language here](#fixer-recommendations-by-locale). Micro-typography is nothing like a standard or a law, what really matters is consistency, so feel free to use your own lists.

Note

Please be advised that JoliTypo works best on **HTML content**; it will also work on plain text, but will be less smart about smart quotes. When fixing a complete HTML document, potential ``, `` and `` tags may be removed.

To fix non HTML content, use the `fixString()` method:

```
use JoliTypo\Fixer;

$fixer = new Fixer(["Trademark", "SmartQuotes"]);
$fixedContent = $fixer->fixString('Here is a "protip(c)"!'); // Here is a “protip©”!
```

CLI usage
=========

[](#cli-usage)

You can run a standalone version of JoliTypo by downloading [the PHAR version](https://github.com/jolicode/JoliTypo/releases/latest)

Run `jolitypo --help` to know how to configure the Fixer.

Installation
============

[](#installation)

Requirements are handled by Composer (libxml and mbstring are required).

```
composer require jolicode/jolitypo

```

*Usage outside composer is also possible, just add the `src/` directory to any PSR-0 compatible autoloader.*

Integrations
============

[](#integrations)

- (Built-in) [Symfony Bundle](src/JoliTypo/Bridge/Symfony)
- (Built-in) [Twig extension](src/JoliTypo/Bridge/Twig)
- (Built-in) [CLI](https://github.com/jolicode/JoliTypo/releases/latest)
- [Drupal module](https://www.drupal.org/project/typography_filter)
- [Joomla plugin](https://github.com/YGomiero/typographe)
- [MODX Extra](https://github.com/jenswittmann/JoliTypo)

🚨 There are no WordPress plugin anymore, feel free to build one!

Available Fixers
================

[](#available-fixers)

Dash
----

[](#dash)

Replaces the simple dash `-` by a ndash `–` between numbers (dates ranges...) and the double `--` by a mdash `—`.

Dimension
---------

[](#dimension)

Replaces the letter x between numbers (`12 x 123`) by a times entity (`×`, the real mathematical symbol).

Ellipsis
--------

[](#ellipsis)

Replaces the three dots `...` by an ellipsis `…`.

SmartQuotes
-----------

[](#smartquotes)

Converts dumb quotes `" "` to all kinds of smart style quotation marks (`“ ”`, `« »`, `„ “`...). Handles a good variety of locales, like English, Arabic, French, Italian, Spanish, Irish, German...

See [the code](https://github.com/jolicode/JoliTypo/blob/master/src/JoliTypo/Fixer/SmartQuotes.php) for more details, and do not forget to specify a locale on the Fixer instance.

This Fixer replaces legacy `EnglishQuotes`, `FrenchQuotes` and `GermanQuotes`.

FrenchNoBreakSpace
------------------

[](#frenchnobreakspace)

Replaces some classic spaces by non-breaking spaces following the French typographic code. No break space are placed before `:`, thin no break space before `;`, `!` and `?`.

NoSpaceBeforeComma
------------------

[](#nospacebeforecomma)

Removes space before `,` and makes sure there is only one space after.

Hyphen (automatic hyphenation)
------------------------------

[](#hyphen-automatic-hyphenation)

Makes use of `org_heigl/hyphenator`, a tool enabling word-hyphenation in PHP. This Hyphenator uses the pattern-files from OpenOffice which are based on the pattern-files created for TeX.

There are only some locales available for this fixer: af\_ZA, ca, da\_DK, de\_AT, de\_CH, de\_DE, en\_GB, en\_UK, et\_EE, fr, hr\_HR, hu\_HU, it\_IT, lt\_LT, nb\_NO, nn\_NO, nl\_NL, pl\_PL, pt\_BR, ro\_RO, ru\_RU, sk\_SK, sl\_SI, sr, zu\_ZA.

You can read more about this fixer on [the official github repository](https://github.com/heiglandreas/Org_Heigl_Hyphenator).

**This Fixer requires a Locale to be set on the Fixer with `$fixer->setLocale('fr_FR');`. Default to `en_GB`.**

**Proper hyphenation is mandatory in justified text** and you should avoid word breaking in titles with this line of CSS: `hyphens:none;`.

⚠ Be aware that the current screen readers are unable to spell correctly the words containing `&shy;` tags. The Hyphen filter should therefore be used with caution or you might reduce your website's accessibility.

CurlyQuote (Smart Quote)
------------------------

[](#curlyquote-smart-quote)

Replaces straight quotes `'` with curly ones `’`. There is one exception to consider: foot and inch marks (minutes and second marks). Purists use prime `′`, this fixer uses straight quotes for compatibility. [Read more about Curly quotes](http://practicaltypography.com/straight-and-curly-quotes.html).

Trademark
---------

[](#trademark)

Handles trade­mark symbol `™`, a registered trade­mark symbol `®`, and a copy­right symbol `©`. This fixer replaces commonly used approximations: `(r)`, `(c)` and `(TM)`. A non-breaking space is put between numbers and copyright symbols too.

Unit (formerly Numeric)
-----------------------

[](#unit-formerly-numeric)

Adds a non-breaking space between a numeral and its unit. Like this: `12_h`, `42_฿` or `88_%`. It was named `Numeric` before release 1.0.2, but BC is kept for now.

**It is really easy to make your own Fixers, feel free to extend the provided ones if they do not fit your typographic rules.**

Fixer recommendations by locale
===============================

[](#fixer-recommendations-by-locale)

en\_GB
------

[](#en_gb)

```
$fixer = new Fixer(['Ellipsis', 'Dimension', 'Unit', 'Dash', 'SmartQuotes', 'NoSpaceBeforeComma', 'CurlyQuote', 'Hyphen', 'Trademark']);
$fixer->setLocale('en_GB');
```

fr\_FR
------

[](#fr_fr)

Those rules apply for most of the recommendations of "Abrégé du code typographique à l'usage de la presse", ISBN: 9782351130667.

```
$fixer = new Fixer(['Ellipsis', 'Dimension', 'Unit', 'Dash', 'SmartQuotes', 'FrenchNoBreakSpace', 'NoSpaceBeforeComma', 'CurlyQuote', 'Hyphen', 'Trademark']);
$fixer->setLocale('fr_FR');
```

fr\_CA
------

[](#fr_ca)

Mostly the same as fr\_FR, but the space before punctuation points is not mandatory.

```
$fixer = new Fixer(['Ellipsis', 'Dimension', 'Unit', 'Dash', 'SmartQuotes', 'NoSpaceBeforeComma', 'CurlyQuote', 'Hyphen', 'Trademark']);
$fixer->setLocale('fr_CA');
```

de\_DE
------

[](#de_de)

Mostly the same as en\_GB, according to [Typefacts](http://typefacts.com/) and [Wikipedia](http://de.wikipedia.org/wiki/Typografie_f%C3%BCr_digitale_Texte).

```
$fixer = new Fixer(['Ellipsis', 'Dimension', 'Unit', 'Dash', 'SmartQuotes', 'NoSpaceBeforeComma', 'CurlyQuote', 'Hyphen', 'Trademark']  );
$fixer->setLocale('de_DE');
```

More to come (contributions welcome!).

Documentation
=============

[](#documentation)

Default usage
-------------

[](#default-usage)

```
$fixer        = new Fixer(['Ellipsis', 'Dimension', 'Dash', 'SmartQuotes', 'CurlyQuote', 'Hyphen']);
$fixedContent = $fixer->fix("Some user contributed HTML which does not use proper glyphs.");

$fixer->setRules(['CurlyQuote']);
$fixedContent = $fixer->fix("I'm only replacing single quotes.");

$fixer->setRules(['Hyphen']);
$fixer->setLocale('en_GB'); // I tell which locale to use for Hyphenation and SmartQuotes
$fixedContent = $fixer->fix("Very long words like Antidisestablishmentarianism.");
```

Define your own Fixer
---------------------

[](#define-your-own-fixer)

If you want to add your own Fixer to the list, you have to implement `JoliTypo\FixerInterface`. Then just give JoliTypo their fully qualified name, or even instance:

```
// by FQN
$fixer = new Fixer([
    'Ellipsis',
    'Acme\\YourOwn\\TypoFixer'
]);
$fixedContent = $fixer->fix("Content fixed by the 2 fixers.");

// or instances, or both
$fixer = new Fixer([
    'Ellipsis',
    'Acme\\YourOwn\\TypoFixer',
    new Acme\\YourOwn\\PonyFixer("Some parameter")
]);
$fixedContent = $fixer->fix("Content fixed by the 3 fixers.");
```

Configure the protected tags
----------------------------

[](#configure-the-protected-tags)

Protected tags is a list of HTML tag names that the DOM parser must avoid. Nothing in those tags will be fixed.

```
$fixer        = new Fixer(['Ellipsis']);
$fixer->setProtectedTags(['pre', 'a']);
$fixedContent = $fixer->fix("Fixed... Not fixed... Fixed... Not Fixed....");
```

Add your own Fixer / Contribute a Fixer
=======================================

[](#add-your-own-fixer--contribute-a-fixer)

- Write tests;
- A Fixer is run on a piece of text, no HTML to deal with;
- Implement `JoliTypo\FixerInterface`;
- Send your Pull request.

### Contribution guidelines

[](#contribution-guidelines)

- You MUST write code in english;
- you MUST follow PSR2 and Symfony coding standard (run `composer cs` on your branch);
- you MUST run the tests (run `composer test`);
- you MUST comply to the MIT license;
- you SHOULD write documentation.

If you add a new Fixer, please provide sources and references about the typographic rule you want to fix.

Compatibility &amp; OS support restrictions
===========================================

[](#compatibility--os-support-restrictions)

- Windows XP : Thin No-Break Space can't be used, all other spaces are ignored, but they do not look bad (normal space).
- Mac OS Snow Leopard : no no-break space, half no-break space, ems and en-dash but doesn't look bad (normal space).

BUT if you use a font (`@font-face` maybe) that contains all those glyphs, there will be no issues.

There is a known [issue](https://bugs.php.net/bug.php?id=62190) preventing JoliTypo to work correctly with APC versions older than 3.1.11.

What can you do to help?
========================

[](#what-can-you-do-to-help)

We need to be able to use this tool everywhere, you can help by providing:

- Wordpress plugin (to replace or complete `wptexturize`)
- Dotclear plugin ...

Also, there is a [Todo list](TODO.md) 😘

License
=======

[](#license)

This piece of code is under MIT License. See the [LICENSE](LICENSE) file.

Alternatives and other implementations
======================================

[](#alternatives-and-other-implementations)

There is already quite a bunch of tools like this one (including good ones). Sadly, some are only for one language, some are running regexp on the whole HTML code ([which is bad](http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454)), some are not tested, some are bundled inside a CMS or a Library, some are not using proper auto-loading, some do not have an open bug tracker... Have a look by yourself:

-
-
- [http://www.bioinformatics.org/phplabware/internal\_utilities/htmLawed/](http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed/)
-
-
-
-
-  (Server side Javascript pre-processor)

Glossary &amp; References
=========================

[](#glossary--references)

Thanks to theses online resources for helping a developer understand typography:

- \[FR\]
-
- \[FR\]
- \[FR\]
-  **is a must-read**
-
- \[FR\] "Abrégé du code typographique à l'usage de la presse", ISBN: 9782351130667
- [https://en.wikipedia.org/wiki/Non-English\_usage\_of\_quotation\_marks](https://en.wikipedia.org/wiki/Non-English_usage_of_quotation_marks)

[![JoliCode is sponsoring this project](https://camo.githubusercontent.com/5dd64f06b500f261fcaac4e3594ca2d4efa01177f217c45a88835dc62140aaa2/68747470733a2f2f6a6f6c69636f64652e636f6d2f6d656469612f6f726967696e616c2f6f73732f666f6f7465722d6769746875622e706e673f7633)](https://jolicode.com/)

###  Health Score

65

—

FairBetter than 99% of packages

Maintenance73

Regular maintenance activity

Popularity57

Moderate usage in the ecosystem

Community37

Small or concentrated contributor base

Maturity81

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 63.2% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~264 days

Recently: every ~392 days

Total

18

Last Release

154d ago

Major Versions

v0.2.0 → 1.02015-12-13

PHP version history (6 changes)v0.1PHP &gt;=5.3.0

1.0.4PHP &gt;=5.6.0

1.0.5PHP &gt;=7.0.0

1.2.0PHP &gt;=7.2.0

v1.3.0PHP &gt;=7.4

v1.5.0PHP &gt;=8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/ebbe48a3e30540f24739602c197ad1212aeb81af96077aed5eb2a300267306bd?d=identicon)[damienalexandre](/maintainers/damienalexandre)

![](https://www.gravatar.com/avatar/c6547f10fb51d1e84f1d5371fb44ee3593c7791432471f0b0adabfb29a18c507?d=identicon)[xavierlacot](/maintainers/xavierlacot)

---

Top Contributors

[![damienalexandre](https://avatars.githubusercontent.com/u/225704?v=4)](https://github.com/damienalexandre "damienalexandre (184 commits)")[![lyrixx](https://avatars.githubusercontent.com/u/408368?v=4)](https://github.com/lyrixx "lyrixx (67 commits)")[![AmraniCh](https://avatars.githubusercontent.com/u/49124992?v=4)](https://github.com/AmraniCh "AmraniCh (7 commits)")[![pyrech](https://avatars.githubusercontent.com/u/2021641?v=4)](https://github.com/pyrech "pyrech (5 commits)")[![HedicGuibert](https://avatars.githubusercontent.com/u/71645693?v=4)](https://github.com/HedicGuibert "HedicGuibert (4 commits)")[![MarionLeHerisson](https://avatars.githubusercontent.com/u/11477247?v=4)](https://github.com/MarionLeHerisson "MarionLeHerisson (3 commits)")[![clairecoloma](https://avatars.githubusercontent.com/u/3041408?v=4)](https://github.com/clairecoloma "clairecoloma (3 commits)")[![remyvanlerberghe](https://avatars.githubusercontent.com/u/25748484?v=4)](https://github.com/remyvanlerberghe "remyvanlerberghe (2 commits)")[![pborreli](https://avatars.githubusercontent.com/u/77759?v=4)](https://github.com/pborreli "pborreli (2 commits)")[![mdarse](https://avatars.githubusercontent.com/u/484720?v=4)](https://github.com/mdarse "mdarse (1 commits)")[![peter279k](https://avatars.githubusercontent.com/u/9021747?v=4)](https://github.com/peter279k "peter279k (1 commits)")[![ternel](https://avatars.githubusercontent.com/u/359558?v=4)](https://github.com/ternel "ternel (1 commits)")[![welcoMattic](https://avatars.githubusercontent.com/u/773875?v=4)](https://github.com/welcoMattic "welcoMattic (1 commits)")[![alexislefebvre](https://avatars.githubusercontent.com/u/2071331?v=4)](https://github.com/alexislefebvre "alexislefebvre (1 commits)")[![xavierlacot](https://avatars.githubusercontent.com/u/177293?v=4)](https://github.com/xavierlacot "xavierlacot (1 commits)")[![Amoifr](https://avatars.githubusercontent.com/u/31698966?v=4)](https://github.com/Amoifr "Amoifr (1 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")[![fvaysh](https://avatars.githubusercontent.com/u/126754021?v=4)](https://github.com/fvaysh "fvaysh (1 commits)")[![j0k3r](https://avatars.githubusercontent.com/u/62333?v=4)](https://github.com/j0k3r "j0k3r (1 commits)")[![jenswittmann](https://avatars.githubusercontent.com/u/5232770?v=4)](https://github.com/jenswittmann "jenswittmann (1 commits)")

---

Tags

hacktoberfestmicrotypographymicrotypography-fixerphptypographyfixertypographyquoteellipsissmartquote

###  Code Quality

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/jolicode-jolitypo/health.svg)

```
[![Health](https://phpackages.com/badges/jolicode-jolitypo/health.svg)](https://phpackages.com/packages/jolicode-jolitypo)
```

###  Alternatives

[friendsofphp/php-cs-fixer

A tool to automatically fix PHP code style

13.5k234.7M20.6k](/packages/friendsofphp-php-cs-fixer)[michelf/php-smartypants

PHP SmartyPants

1115.3M30](/packages/michelf-php-smartypants)[stechstudio/laravel-php-cs-fixer

Easily format your Laravel Code with this Configuration file and accompanying artisan command.

146718.6k2](/packages/stechstudio-laravel-php-cs-fixer)[fadion/fixerio

Wrapper for Fixer.io

49337.7k](/packages/fadion-fixerio)[stevebauman/unfinalize

Permanently remove final keywords from vendor packages.

14423.1k](/packages/stevebauman-unfinalize)[nilportugues/php_backslasher

Adds all PHP internal functions to its namespace by adding backslash to them. Improves the application's performance when OPCache is on.

889.3k18](/packages/nilportugues-php-backslasher)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
