jacksleight / statamic-bard-mutator

This Statamic addon allows you to modify the data and tags rendered by the Bard fieldtype, giving you full control over the final HTML.
https://statamic.com/addons/jacksleight/bard-mutator
MIT License
18 stars 3 forks source link

Shareable mutators #27

Closed daun closed 2 days ago

daun commented 1 month ago

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 commented 1 month ago

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

jacksleight commented 1 month ago

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!

daun commented 1 month ago

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.

jacksleight commented 1 month ago

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.

daun commented 1 month ago

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 :)

jacksleight commented 2 days ago

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