PHPackages                             esheep/twigs - 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. esheep/twigs

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

esheep/twigs
============

A framework-agnostic Twig extension that bundles useful functions, filters, and tags into a single entry point.

v0.0.1(1w ago)03↓100%MITPHPPHP &gt;=8.1

Since Mar 10Pushed 1w agoCompare

[ Source](https://github.com/yaserahmady/twigs)[ Packagist](https://packagist.org/packages/esheep/twigs)[ RSS](/packages/esheep-twigs/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (6)Versions (2)Used By (0)

Twigs
=====

[](#twigs)

A framework-agnostic Twig extension that bundles useful functions, filters, and tags into a single entry point.

Installation
------------

[](#installation)

```
composer require esheep/twigs
```

Setup
-----

[](#setup)

Register the extension with your Twig environment:

```
$twig->addExtension(new \eSheep\Twigs\Extension());
```

### Constructor Options

[](#constructor-options)

```
use eSheep\Twigs\Extension;
use TalesFromADev\TailwindMerge\TailwindMerge;

$twig->addExtension(new Extension(
    // Optional: inject a pre-configured TailwindMerge instance
    tailwindMerge: new TailwindMerge(additionalConfiguration: [...]),

    // Optional: default options for the merge_attributes filter
    mergeOptions: [
        'remove_duplicate_classes' => true, // default: true
        'tailwind_merge' => true,           // default: true
    ],
));
```

Functions
---------

[](#functions)

### `html_tag` / `tag`

[](#html_tag--tag)

Generates an HTML tag.

```
{{ html_tag('div', {class: 'container', id: 'main'}) }}
{#  #}

{{ tag('p', {text: 'Hello '}) }}
{# Hello &lt;world&gt; #}

{{ tag('p', {html: 'Bold'}) }}
{# Bold #}
```

- `text`: HTML-encodes the value and uses it as the tag body.
- `html`: Uses the value as raw HTML tag body.
- All other keys are rendered as HTML attributes.

### `html_attr` / `attr`

[](#html_attr--attr)

Renders an attribute array as an HTML attribute string.

```

{#  #}
```

### `html_cva` / `cva`

[](#html_cva--cva)

Creates a [CVA (Class Variant Authority)](https://cva.style/) instance for managing component class variants.

```
{% set button = cva('btn', {
    color: {primary: 'btn-primary', danger: 'btn-danger'},
    size: {sm: 'btn-sm', lg: 'btn-lg'}
}, [], {color: 'primary', size: 'sm'}) %}

{#  #}
```

Filters
-------

[](#filters)

### `html_attr` / `attr`

[](#html_attr--attr-1)

Modifies the attributes of an existing HTML tag string.

```
{{ ''|attr({class: 'new', id: 'test'}) }}
{#  #}
```

### `merge_attributes`

[](#merge_attributes)

Merges two attribute arrays with optional class deduplication and Tailwind class conflict resolution. The result can be passed to `attr()` to render as HTML attributes.

```
{% set base = {class: 'p-4 text-red-500', id: 'hero'} %}
{% set extra = {class: 'p-2 font-bold', 'hx-get': '/api'} %}

{# Basic merge — deduplicates classes and resolves Tailwind conflicts by default #}

{#  #}

{# Override options per call #}
{% set merged = base|merge_attributes(extra, {tailwind_merge: false}) %}
{% set merged = base|merge_attributes(extra, {remove_duplicate_classes: false}) %}
```

**Options** (third argument, overrides extension defaults):

KeyTypeDefaultDescription`remove_duplicate_classes``bool``true`Deduplicate class names after merging`tailwind_merge``bool``true`Resolve Tailwind CSS class conflicts### `tailwind_merge` / `tw_merge`

[](#tailwind_merge--tw_merge)

Merges Tailwind CSS classes, intelligently resolving conflicts.

```
{{ 'px-2 py-1 bg-red-500'|tw_merge('p-4') }}
{# bg-red-500 p-4 #}

{{ 'text-red-500'|tw_merge('text-blue-500') }}
{# text-blue-500 #}
```

Tags
----

[](#tags)

### `{% html_tag %}` / `{% tag %}`

[](#-html_tag----tag-)

Block-level tag generation. Captures content between the tags.

```
{% tag 'nav' with {class: 'main-nav', role: 'navigation'} %}
    Home
    About
{% endtag %}

{% html_tag 'section' with {id: 'hero', class: 'full-width'} %}
    Welcome
{% endhtml_tag %}
```

Attribute Normalization
-----------------------

[](#attribute-normalization)

Attributes are normalized automatically:

- **`class`** strings are split into arrays and deduplicated on merge.
- **`style`** strings are parsed into property/value pairs.
- **Data attributes** like `data-foo` are collapsed into `data: {foo: ...}`.
- **`removeClass`** pseudo-attribute removes classes:

```
{{ ''|attr({removeClass: 'b'}) }}
{#  #}
```

Supported data attribute prefixes: `aria`, `data`, `data-hx`, `data-ng`, `hx`, `ng`.

Provenance
----------

[](#provenance)

Some code in this package is ported from [Craft CMS](https://github.com/craftcms/cms). See [PROVENANCE.md](PROVENANCE.md) for details on what was ported and from which commit.

License
-------

[](#license)

MIT. See [LICENSE](LICENSE).

###  Health Score

36

—

LowBetter than 83% of packages

Maintenance98

Actively maintained with recent releases

Popularity4

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity32

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% 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

Unknown

Total

1

Last Release

12d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/2b60184f4b2d44fb68c9c725dc8584397f4749624d10aceabc6549efc4027e3f?d=identicon)[esheep](/maintainers/esheep)

---

Top Contributors

[![yaserahmady](https://avatars.githubusercontent.com/u/51824028?v=4)](https://github.com/yaserahmady "yaserahmady (1 commits)")

---

Tags

twightmltailwindcvatailwind-merge

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/esheep-twigs/health.svg)

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

###  Alternatives

[twig/string-extra

A Twig extension for Symfony String

21944.4M100](/packages/twig-string-extra)[twig/markdown-extra

A Twig extension for Markdown

12113.8M69](/packages/twig-markdown-extra)[twig/html-extra

A Twig extension for HTML

777.0M32](/packages/twig-html-extra)[tales-from-a-dev/twig-tailwind-extra

A Twig extension for Tailwind

31714.5k7](/packages/tales-from-a-dev-twig-tailwind-extra)[spress/spress

Static site generator with blogs support

37536.1k](/packages/spress-spress)[twig/cache-extra

A Twig extension for Symfony Cache

412.0M15](/packages/twig-cache-extra)

PHPackages © 2026

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