statamic-bard-mutator icon indicating copy to clipboard operation
statamic-bard-mutator copied to clipboard

Shareable mutators

Open daun opened this issue 1 year ago • 5 comments

An idea: I've been refactoring my mutators from callbacks in service containers out into separate invokable classes. Turns out that's a great format for sharing them. How do you feel about developing a shareable format and bundling the examples inside the package? I could obviously create my own composer package with a personal set of mutators, but I would love the ones currently in the docs available to include, and it'd be interesting to see what people come up with :)

Just wanted to throw this out. Feel free to close immediately.

Example Mutator

Using an invokable object allows combining multiple Mutator::* types into a single shareable "task".

use JackSleight\StatamicBardMutator\Facades\Mutator;

class WrapTablesInDiv
{
    public function __invoke(string $class = 'table-wrapper'): void
    {
        Mutator::html('table', function ($value) use ($class) {
            $inner = array_splice($value, 2, count($value), [0]);
            return ['div', ['class' => $class], $value, ...$inner];
        });
    }
}

Example Service Provider

The provider just invokes each mutator. Probably could have a better API.

use Illuminate\Support\ServiceProvider;
use Statamic\Fieldtypes\Bard\Augmentor;

class BardCustomizationProvider extends ServiceProvider
{
    protected $mutators = [
        \App\Mutators\AutoGenerateHeadingIds::class => ['levels' => [1, 2, 3]],
        \App\Mutators\WrapTablesInDiv::class => ['class' => 'responsive-table'],
        \App\Mutators\MarkExternalLinks::class,
    ];

    public function boot(): void
    {
        foreach ($this->mutators as $key => $value) {
            if (is_string($key)) {
                $mutator = $key;
                $args = $value ?: [];
            } else {
                $mutator = $value;
                $args = [];
            }
            (new $mutator)(...$args);
        }
    }
}

daun avatar Jul 17 '24 12:07 daun

If this sounds like something you'd like to support going forward, I'm happy to create a PR to get things started.

daun avatar Jul 17 '24 12:07 daun

Have you seen my secret roadmap? 😄

I have a plan for some major changes to the way mutators are defined/registered/configured in v3, and making them class based is part of that. I am also toying with the idea of bundling in some of the examples, although that would only make sense for the most generic/general purpose ones.

If this sounds like something you'd like to support going forward, I'm happy to create a PR to get things started.

I really appreciate the offer, but I'm going to be doing this as part of some bigger changes so wouldn't want you to waste your time if that didn't then fit with the other stuff. If you'd like to help test/give feedback when they're ready though that would be great!

jacksleight avatar Jul 17 '24 13:07 jacksleight

Hehe, sounds great! I'll hold my horses then and see how you decide to implement it. Feel free to ping me if you need someone to try things out.

daun avatar Jul 17 '24 14:07 daun

Still a work in progress but check out https://github.com/jacksleight/statamic-bard-mutator/pull/30.

There's one example plugin (and tests) where you can see how it currently works.

jacksleight avatar Jul 29 '24 15:07 jacksleight

Looks great. Really intuitive. The surrounding refactorings are way above my head, but the public Plugin API matches pretty much exactly what I was going for :)

daun avatar Jul 29 '24 16:07 daun

This has now been released in v3: https://github.com/jacksleight/statamic-bard-mutator/releases/tag/3.0.0

jacksleight avatar Sep 03 '24 16:09 jacksleight