PHPackages                             akankov/twig-compress-html - 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. [Templating &amp; Views](/categories/templating)
4. /
5. akankov/twig-compress-html

ActiveLibrary[Templating &amp; Views](/categories/templating)

akankov/twig-compress-html
==========================

Twig 3 extension wrapping akankov/html-min: provides an html\_min filter and a {% htmlmin %}...{% endhtmlmin %} block tag, plus an optional Symfony bundle.

v1.4.2(3w ago)156.1k↓15.5%MITPHPPHP 8.3.\* || 8.4.\* || 8.5.\*CI passing

Since May 1Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/akankov/twig-compress-html)[ Packagist](https://packagist.org/packages/akankov/twig-compress-html)[ Fund](https://ko-fi.com/alekseikankov)[ RSS](/packages/akankov-twig-compress-html/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (5)Dependencies (53)Versions (10)Used By (0)

[![CI](https://github.com/akankov/twig-compress-html/actions/workflows/ci.yml/badge.svg)](https://github.com/akankov/twig-compress-html/actions/workflows/ci.yml)[![Latest Stable Version](https://camo.githubusercontent.com/3235b5cd702d61a4b499ef17c0656efa9b1be0fbee4e8fb7b468c0834867ef46/687474703a2f2f706f7365722e707567782e6f72672f616b616e6b6f762f747769672d636f6d70726573732d68746d6c2f76)](https://packagist.org/packages/akankov/twig-compress-html)[![Monthly Downloads](https://camo.githubusercontent.com/5bd46e9028077cd7d0e5da9d95a2606bd0d04e42ac935b3aa6d1db7662884ff2/687474703a2f2f706f7365722e707567782e6f72672f616b616e6b6f762f747769672d636f6d70726573732d68746d6c2f642f6d6f6e74686c79)](https://packagist.org/packages/akankov/twig-compress-html)[![Dependents](https://camo.githubusercontent.com/3f6a3fc3ff352413695ed7fd77608c991e05005ff06bea0d98476efee44c9203/687474703a2f2f706f7365722e707567782e6f72672f616b616e6b6f762f747769672d636f6d70726573732d68746d6c2f646570656e64656e7473)](https://packagist.org/packages/akankov/twig-compress-html)[![License](https://camo.githubusercontent.com/0d78b836a43fde4917d5fa34f1c4627a587b001bbf556495b0b3129c2ae26aa6/687474703a2f2f706f7365722e707567782e6f72672f616b616e6b6f762f747769672d636f6d70726573732d68746d6c2f6c6963656e7365)](https://packagist.org/packages/akankov/twig-compress-html)

twig-compress-html
==================

[](#twig-compress-html)

A Twig 3 extension wrapping [`akankov/html-min`](https://packagist.org/packages/akankov/html-min) — exposes an `html_min` filter and an `{% htmlmin %}...{% endhtmlmin %}` block tag, with an optional Symfony bundle for auto-registration.

Requirements
------------

[](#requirements)

- PHP `8.3.* || 8.4.* || 8.5.*`
- `twig/twig` `^3.0`
- `akankov/html-min` `^2.9`

Install
-------

[](#install)

```
composer require akankov/twig-compress-html
```

Plain Twig usage
----------------

[](#plain-twig-usage)

```
use Akankov\HtmlMin\HtmlMin;
use Akankov\TwigCompressHtml\HtmlMinExtension;
use Akankov\TwigCompressHtml\HtmlMinRuntime;
use Twig\Environment;
use Twig\Loader\FilesystemLoader;
use Twig\RuntimeLoader\FactoryRuntimeLoader;

$twig = new Environment(new FilesystemLoader(__DIR__.'/templates'));
$twig->addExtension(new HtmlMinExtension());
$twig->addRuntimeLoader(new FactoryRuntimeLoader([
    HtmlMinRuntime::class => static fn () => new HtmlMinRuntime(new HtmlMin()),
]));
```

### Filter

[](#filter)

```
{{ rawHtml|html_min }}
```

### Block tag

[](#block-tag)

```
{% htmlmin %}

    {{ content }}

{% endhtmlmin %}
```

The tag captures rendered output (variables are escaped first by Twig's autoescape, then minified), so it's safe to interpolate user data inside.

Symfony usage
-------------

[](#symfony-usage)

Register the bundle in `config/bundles.php`:

```
return [
    // ...
    Akankov\TwigCompressHtml\Bundle\AkankovTwigCompressHtmlBundle::class => ['all' => true],
];
```

Optionally tune `HtmlMin` via `config/packages/akankov_twig_compress_html.yaml`:

```
akankov_twig_compress_html:
    remove_comments: true
    sum_up_whitespace: true
    optimize_attributes: true
    sort_html_attributes: true
    remove_omitted_quotes: false
    minify_inline_css: true
    local_domains: ['example.com']
```

The filter and tag become available in all templates automatically.

### Configuration

[](#configuration)

Every config key is a snake\_case mirror of a property on `Akankov\HtmlMin\Config\MinifierOptions`; the bundle camel-cases them and builds the options object that backs the shared `HtmlMin` service, so:

```
remove_comments: true       # → MinifierOptions::$removeComments
sum_up_whitespace: true     # → MinifierOptions::$sumUpWhitespace
local_domains: ['a.test']   # → MinifierOptions::$localDomains
```

All of the engine's options are accepted — the 27 boolean toggles plus the list options `local_domains`, `special_html_comments_starting_with`, `special_html_comments_ending_with`, `special_script_tags`, and `template_logic_syntax_in_special_script_tags`. Any key you omit falls through to the engine's own default, so the bundle never pins (or drifts from) those defaults. This matches the surface exposed by the Laravel binding's `config/htmlmin.php`.

### Response minification (opt-in)

[](#response-minification-opt-in)

To minify whole `text/html` responses — not just `{% htmlmin %}` blocks — enable the `kernel.response` listener. It is **off by default** (the bundle never adds it to the response pipeline on its own), mirroring the Laravel binding's `MinifyHtmlResponseMiddleware`:

```
akankov_twig_compress_html:
    minify_responses: true
```

Sub-requests, streamed responses, and non-`text/html` responses pass through untouched, so it is safe in front of a mixed JSON / HTML application.

What "pass through" covers, precisely:

- **Streamed responses** (`StreamedResponse`, `BinaryFileResponse`) are never buffered or minified — the listener only touches responses whose body it can read as a string.
- **Partial content** (`206` responses to range requests) is skipped by the same mechanism in practice — range responses are produced as binary-file responses; minifying a byte range of HTML would corrupt it.
- **ESI/SSI fragments**: the listener runs only on the main request, so edge-side includes assembled by a proxy are minified per-fragment only if your proxy requests them as main requests against this app — in that case each fragment is valid standalone HTML and minifies safely. Fragments rendered as Symfony sub-requests pass through untouched.

### Console command

[](#console-command)

With `symfony/console` installed, the bundle registers `html-min:check` — a CI/dev smoke-check that minifies a file in memory and reports the byte savings without writing to disk (mirrors the Laravel binding's Artisan command):

```
bin/console html-min:check templates/page.html
# [OK] Reduced from 4.2 KB to 3.1 KB (-26.3%)
```

It exits `0` on success and `1` if the file cannot be read.

Versioning
----------

[](#versioning)

This package follows [Semantic Versioning](https://semver.org/). From **1.0.0** onward the public surface — the `html_min` filter, the `{% htmlmin %}` block tag, the Symfony bundle's config keys, and the opt-in response listener — is stable; breaking changes are reserved for a new major version. The underlying engine is tracked via a caret constraint (`akankov/html-min: ^2.9`), so it picks up engine minor/patch releases automatically.

Tests
-----

[](#tests)

```
composer install
vendor/bin/phpunit

# line coverage + floor enforcement (needs pcov or xdebug)
make coverage
```

License
-------

[](#license)

MIT

###  Health Score

52

—

FairBetter than 96% of packages

Maintenance94

Actively maintained with recent releases

Popularity34

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 96.7% 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 ~9 days

Total

7

Last Release

25d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1974569?v=4)[Aleksei Kankov](/maintainers/akankov)[@akankov](https://github.com/akankov)

---

Top Contributors

[![akankov](https://avatars.githubusercontent.com/u/1974569?v=4)](https://github.com/akankov "akankov (29 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")

---

Tags

symfonybundletwightmlminifycompresshtml min

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Rector

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/akankov-twig-compress-html/health.svg)

```
[![Health](https://phpackages.com/badges/akankov-twig-compress-html/health.svg)](https://phpackages.com/packages/akankov-twig-compress-html)
```

###  Alternatives

[symfony/ux-twig-component

Twig components for Symfony

22018.6M379](/packages/symfony-ux-twig-component)[symfony/ux-live-component

Live components for Symfony

1647.0M136](/packages/symfony-ux-live-component)[nochso/html-compress-twig

Twig extension for compressing HTML and inline CSS/Javascript

79471.5k8](/packages/nochso-html-compress-twig)[voku/html-compress-twig

Twig extension for compressing HTML

282.4M](/packages/voku-html-compress-twig)[yellowskies/qr-code-bundle

Symfony Barcode &amp; QR Code Generator Bundle with Twig extension

37711.6k](/packages/yellowskies-qr-code-bundle)[mati365/ckeditor5-symfony

CKEditor 5 integration for Symfony

262.6k](/packages/mati365-ckeditor5-symfony)

PHPackages © 2026

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