Closed jacksleight closed 2 years ago
@el-schneider
Using this feature you can now use Bard Texstyle's span node to apply classes to links. To do this first ensure you're using the new Bard Mutator tag (necessary to add the context data):
{{ bmu:bard_field }}
Then add the following mutator:
Mutator::tag('link', function ($tag, $data, $meta) {
if (($meta['next']->type ?? null) === 'bts_span') {
$tag[0]['attrs']['class'] = $meta['next']->attrs->class ?? null;
}
return $tag;
});
This will run on all link
marks, checking if the following mark is a bts_span
, and if so copy the class value from that mark to the tag. This is clean and simple and works, and it may be fine for your purposes, but it does have a couple of issues that you should be aware of:
bts_span
mark will directly follow the link
mark. While it will always come after, it may not be next if other marks are being used as well.<span>
tag will still be rendered, which you may not want.These issues can be resolved within tag mutators, but it's not recommended. Instead you can use another new feature included in this PR, root mutators.
Root mutators run before any rendering starts, and give you the opportunity to manipulate the raw Bard data. They're an advanced feature that give you access to the entire ProseMirror document. Using a root mutator you can traverse through all text
nodes, check if they contain link
and bts_span
marks, and if so alter the data accordingly. You can then use a simple link
tag mutator to apply that class to the HTML tag.
use JackSleight\StatamicBardMutator\Facades\Mutator;
Mutator::data('text', function ($data) {
$marks = collect($data->marks ?? []);
$link = $marks->search(fn ($m) => $m->type === 'link');
$span = $marks->search(fn ($m) => $m->type === 'bts_span');
if ($link !== false && $span !== false) {
$data->marks[$link]->attrs->class = $data->marks[$span]->attrs->class ?? null;
unset($data->marks[$span]);
}
});
Mutator::tag('link', function ($tag, $data) {
$tag[0]['attrs']['class'] = $data->attrs->class ?? null;
return $tag;
});
While not as simple, this is more robust and ensures you're only rendering what you need.
I've not yet finalised the root mutator API design so it may change a little before release.
When using GraphQL you can override the field with a custom version that augments the value via Bard Mutator, see https://statamic.dev/graphql#custom-fields:
use Statamic\Facades\GraphQL;
GraphQL::addField('Entry_Pages_Pages', 'my_content', function () {
return [
'type' => GraphQL::string(),
'resolve' => function ($entry) {
return Mutator::render($entry->augmentedValue('my_content'));
},
];
});
Again, still figuring out the final details on this so it may change slightly.
This adds contextual metadata such as parent and previous/next sibling information to mutators.