PHPackages                             daun/statamic-bard-mutators - 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. daun/statamic-bard-mutators

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

daun/statamic-bard-mutators
===========================

A collection of plugins for the Statamic Bard Mutator addon

1.5.1(1mo ago)059MITPHPPHP ^8.1CI failing

Since Mar 13Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/daun/statamic-bard-mutators)[ Packagist](https://packagist.org/packages/daun/statamic-bard-mutators)[ Docs](https://github.com/daun/statamic-bard-mutators)[ RSS](/packages/daun-statamic-bard-mutators/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (17)Versions (19)Used By (0)

🧱 Statamic Bard Mutators
========================

[](#-statamic-bard-mutators)

A collection of mutators for transforming [Statamic Bard](https://statamic.dev/fieldtypes/bard) content.

Mutators are implemented as plugins for Jack Sleight's [Bard Mutator Addon](https://statamic.com/addons/jacksleight/bard-mutator).

Mutators
--------

[](#mutators)

- [Lazy Load Images](#lazy-load-images) — add `loading=lazy` and `decoding=async` to images
- [Generate Heading IDs](#generate-heading-ids) — add `id` to headings
- [Insert Heading Permalinks](#insert-heading-permalinks) — insert permalinks into headings
- [Normalize Heading Levels](#normalize-heading-levels) — close gaps in the heading hierarchy
- [Shift Heading Levels](#shift-heading-levels) — shift or clamp heading levels
- [Mark External Links](#mark-external-links) — add `target` and `rel` to external links
- [Mark Asset Links](#mark-asset-links) — add `download` to asset links
- [Semantic Blockquotes](#semantic-blockquotes) — wrap blockquotes in `figure` with `figcaption`
- [Wrap Tables](#wrap-tables) — move tables into a horizontally scrollable container
- [Remove List Item Paragraphs](#remove-list-item-paragraphs) — remove `p` wrappers around `li` text

[See the full list of mutators →](#all-mutators)

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

[](#installation)

Install the package via composer:

```
composer require daun/statamic-bard-mutators
```

Registration
------------

[](#registration)

Register any mutators you want to use from the `Mutator` facade. Options can be passed as arguments to the constructor. You can read more about [class-based mutator plugins](https://jacksleight.dev/docs/bard-mutator/plugins#class-based-plugins)in the addon readme.

```
use JackSleight\StatamicBardMutator\Facades\Mutator;
use Daun\BardMutators\MarkExternalLinks;

Mutator::plugin(new MarkExternalLinks());
```

All Mutators
------------

[](#all-mutators)

### Mark External Links

[](#mark-external-links)

Mark external links with `target="_blank"` and `rel="external"`.

```

External link

External link
```

```
new MarkExternalLinks();

// Optionally customize the `target` and `rel` attributes
new MarkExternalLinks(
    target: '_blank',
    rel: 'noopener noreferrer'
);
```

### Mark Asset Links

[](#mark-asset-links)

Mark links to assets with `download="filename.ext"`.

```

Download video

Download video
```

```
new MarkAssetLinks();

// Use original filename as download filename hint
// Requires `daun/statamic-original-filename` package
new MarkAssetLinks(
    useOriginalFilename: true
);
```

### Generate Heading IDs

[](#generate-heading-ids)

Adds an `id` attribute to headings based on their content.

```

Heading

Heading
```

```
new GenerateHeadingIds();

// Customize heading levels to generate IDs for and add a prefix to generated IDs
new GenerateHeadingIds(
    levels: [2, 3],
    prefix: 'section-'
);
```

### Insert Heading Permalinks

[](#insert-heading-permalinks)

Insert a permalink inside each heading pointing to its own `id`. Permalinks are only added to headings that already have an `id` — register `GenerateHeadingIds`beforehand if you want every heading to get a permalink.

```

Introduction

        #

    Introduction

```

The icon is wrapped in `` so a screen reader announces only the link's `aria-label`, not the icon.

```
// Register GenerateHeadingIds first so headings get an id to link to.
Mutator::plugin(new GenerateHeadingIds());
Mutator::plugin(new InsertHeadingPermalinks());

// Append the permalink instead of prepending it.
new InsertHeadingPermalinks(behavior: 'append');

// Customize the icon (text, emoji, or raw HTML for an inline SVG).
new InsertHeadingPermalinks(icon: '🔗');
new InsertHeadingPermalinks(icon: '');

// Customize the accessible label. Use `{text}` as a placeholder for the
// resolved heading text.
new InsertHeadingPermalinks(label: 'Jump to {text}');

// Limit which heading levels get a permalink, add a class.
new InsertHeadingPermalinks(
    levels: [2, 3],
    class: 'heading-permalink',
);
```

### Semantic Blockquotes

[](#semantic-blockquotes)

Wraps blockquotes in a `figure` element and moves the author/source into a `figcaption` element.

```

    Quote
    — Author

        Quote

        Author

```

```
new SemanticBlockquotes();

// Optionally add a class to the figure element
new SemanticBlockquotes(
    class: 'quote'
);
```

Wrap Tables
-----------

[](#wrap-tables)

Wraps tables in a `div` element to allow for horizontal scrolling on smaller screens.

```

...

    ...

```

```
new WrapTables();

// Optionally use a custom tag or add a class to the wrapper element
new WrapTables(
    tag: 'section',
    class: 'table'
);
```

### Normalize Heading Levels

[](#normalize-heading-levels)

Close skip-level gaps in the heading hierarchy by pulling deep headings up (e.g. `` followed by `` becomes `` followed by ``). The first heading is left at whatever level it starts, and going back up to a shallower level is always allowed.

```

Section
Subsection

Section
Subsection
```

```
new NormalizeHeadingLevels();
```

This pairs naturally with `ShiftHeadingLevels` — register `NormalizeHeadingLevels`first to clean the hierarchy, then `ShiftHeadingLevels` to position the cleaned tree (e.g. `min: 2` to keep `` reserved for the page title).

### Shift Heading Levels

[](#shift-heading-levels)

Shift heading levels up or down. Useful when a Bard field is rendered under a page `` and headings inside the field should start lower in the outline.

```

Section
Subsection

Section
Subsection
```

```
// Shift every heading down (or up, with negative values). Clamped to h6.
new ShiftHeadingLevels(shift: 1);

// Clamp every heading to be at least h2 (e.g. to keep h1 reserved for the page title).
new ShiftHeadingLevels(min: 2);

// Shift the entire document so its shallowest heading becomes h2,
// preserving relative hierarchy. Mutually exclusive with `shift`.
new ShiftHeadingLevels(start: 2);

// Combine: shift down, then clamp at h2.
new ShiftHeadingLevels(shift: 1, min: 2);
```

### Lazy Load Images

[](#lazy-load-images)

Add `loading="lazy"` and `decoding="async"` to images for better page performance.

```

```

```
new LazyLoadImages();

// Skip lazy loading on the first image if it sits at the top of the document
// (i.e. is the first node, or appears in the first paragraph or figure).
// Useful for avoiding lazy loading on a likely LCP image.
new LazyLoadImages(
    skipFirst: true
);

// Switch to lazysizes.js markup. The image gets a `lazyload` class, its `src`
// is moved to `data-src`, and the native `loading`/`decoding` attributes are
// not added. Pass an optional class name to override `lazyload`.
(new LazyLoadImages())->usingLazysizes();
(new LazyLoadImages())->usingLazysizes('lazy-load');

// Combine with skipFirst: the LCP image is left untouched (no lazyload class,
// no data-src swap) so the browser loads it eagerly.
(new LazyLoadImages(skipFirst: true))->usingLazysizes();
```

```

```

Remove List Item Paragraphs
---------------------------

[](#remove-list-item-paragraphs)

Remove the paragraphs that tiptap automatically adds inside list items.

```

    List item

    List item

```

```
new RemoveListItemParagraphs();
```

License
-------

[](#license)

[MIT](https://opensource.org/licenses/MIT)

###  Health Score

42

—

FairBetter than 88% of packages

Maintenance89

Actively maintained with recent releases

Popularity8

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity55

Maturing project, gaining track record

 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

Every ~46 days

Recently: every ~21 days

Total

10

Last Release

57d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/31ac2b3787ded290b6bac87b937abf4f267483e4da64731bfb256a942bb669ca?d=identicon)[daun](/maintainers/daun)

---

Top Contributors

[![daun](https://avatars.githubusercontent.com/u/22225348?v=4)](https://github.com/daun "daun (47 commits)")

---

Tags

bardpluginsstatamicstatamicbard

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/daun-statamic-bard-mutators/health.svg)

```
[![Health](https://phpackages.com/badges/daun-statamic-bard-mutators/health.svg)](https://phpackages.com/packages/daun-statamic-bard-mutators)
```

###  Alternatives

[statamic-rad-pack/runway

Eloquently manage your database models in Statamic.

135224.7k7](/packages/statamic-rad-pack-runway)[statamic/statamic

Statamic

829179.5k](/packages/statamic-statamic)[duncanmcclean/statamic-cargo

Comprehensive e-commerce addon for Statamic. Build bespoke e-commerce sites without the complexity.

3416.7k](/packages/duncanmcclean-statamic-cargo)[marcorieser/statamic-livewire

A Laravel Livewire integration for Statamic.

23111.5k14](/packages/marcorieser-statamic-livewire)[aerni/livewire-forms

A Statamic forms framework powered by Laravel Livewire

2915.1k](/packages/aerni-livewire-forms)[visuellverstehen/statamic-classify

A useful helper to add CSS classes to all HTML tags generated by the bard editor.

20121.3k](/packages/visuellverstehen-statamic-classify)

PHPackages © 2026

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