When working with Statamic Bard, I wanted to find and replace certain occurrence of a word – say find “Lorem ipsum” and replace with “LOREM IPSUM”. I used this great addon called Bard Mutator (v1 and v2). I’m using Statamic v3.4 with Tiptap v2 and Bard Mutator v2.

To get started:

  • Make sure you have a bard field in your statamic blueprint
  • Install Bard Mutator from the link above
  • Add the following snippet that lets you perform advanced operations to a service provider. Either src/Providers/AppServiceProvider or a separate Service Provider will do.
$this->app->bind(
    TiptapEditor::class,
    JackSleightStatamicBardMutatorEditor::class
);

This is the content I have in my bard field (repeated multiple times) so we can see how to replace just once and all occurrences if we want to.

To replace only once in each paragraph:

Mutator::data('paragraph', function ($data, $meta){
            if (empty($data->content)) {
                return;
            }

            foreach ($data->content as $i => $node) {
                if (isset($node->text)) {
                    $regex = '/^(.*?)bLorem Ipsumb(.*)$/';
                    if (!preg_match($regex, $node->text, $match)) {
                        continue;
                    }

                    [, $before, $after] = $match;
                    array_splice($data->content, $i, 1, [
                        (object)['type' => 'text', 'text' => $before],
                        (object)['type' => 'text', 'text' => 'LOREM IPSUM'],
                        (object)['type' => 'text', 'text' => $after],
                    ]);
                    break;
                }
                
            }
});

To replace only once in the entire article:

I used $meta which gives us access to the root tag. Bard data mutator for paragraph is triggered once for each paragraph in the bard field. So you need access to $meta['root'] which is great to store shared variables.

 Mutator::data('paragraph', function ($data, $meta){
            if (empty($data->content)) {
                return;
            }

            if (isset($meta['root']->replaced) && $meta['root']->replaced){
                return;
            }

            foreach ($data->content as $i => $node) {
                if (isset($node->text)) {
                    $regex = '/^(.*?)bLorem Ipsumb(.*)$/';
                    if (!preg_match($regex, $node->text, $match)) {
                        continue;
                    }

                    [, $before, $after] = $match;
                    array_splice($data->content, $i, 1, [
                        (object)['type' => 'text', 'text' => $before],
                        (object)['type' => 'text', 'text' => 'DUMMY TEXT'],
                        (object)['type' => 'text', 'text' => $after],
                    ]);
                    $meta['root']->replaced = true;
                    break;
                }
                
            }
});