The use of parenthesis in a caption is confusing Kirby. I understand why. Consider the following.
(image: lobster-boat-blockade.jpg caption: From Left to Right: Jay O'Hara (holding photo), Attorney Matt Pawa (speaking to reporters))
The parenthesis in the caption are closing the “shortcode”. I could tell the client to use brackets, but that’s just another thing they have to remember. I’d be nice if the “shortcodes” could use some other less common character to open and close them.
Unfortunately, there still is no way to escape parenthesis inside Kirbytags, at least not any I know of. So, you can’t use parenthesis inside Kirbytags. A work around would be to use some other characters like square brackets and replace those with a Kirbytext post filter, but as you said, it’s more difficult for clients to remember.
So I’m not sure this is the most efficient way of doing it but this solution seems to be working in my tests
# Fix the () nested inside the kirbytags
'kirbytags:before' => function ($text, array $data = [], array $options = []) {
// KirbyTags have not been parsed
$text = preg_replace_callback('/\((?:[^()]+|(?R))*+\)/', function ($matches) {
// Loop through each tag and perform a second serach
foreach ($matches as $match) :
// First trim the () at the beginning and at the end
$match = substr($match , 1 , -1);
// Then look for () inside the string and replace them with another character
$match = str_replace('(', '⎣', $match);
$match = str_replace(')', '⎦', $match);
// Add back the two () at the beginning and the end
$match = "({$match})";
// Return the string
return $match;
endforeach;
# Return al the kirbytags
return $matches;
}, $text);
return $text;
},
# Add back the () we swapped previously
'kirbytags:after' => function ($text, array $data = [], array $options = []) {
$text = preg_replace_callback('/\⎣|\⎦/', function ($matches) {
// Loop through each tag and swap the characters
foreach ($matches as $match) :
// Swap back the correct ()
$match = ($match == "⎣" ) ? "(" : ")";
// Return the string
return $match;
endforeach;
# Return al the kirbytags
return $matches;
}, $text);
return $text;
},
For example, you could add this hook in config.php:
'hooks' => [
'kirbytags:before' => function ($text, $data, $options) {
// KirbyTags have not been parsed
$text = preg_replace_callback('/\((?:[^()]+|(?R))*+\)/', function ($matches) {
// Loop through each tag and perform a second serach
foreach ($matches as $match) :
// First trim the () at the beginning and at the end
$match = substr($match , 1 , -1);
// Then look for () inside the string and replace them with another character
$match = str_replace('(', '⎣', $match);
$match = str_replace(')', '⎦', $match);
// Add back the two () at the beginning and the end
$match = "({$match})";
// Return the string
return $match;
endforeach;
# Return al the kirbytags
return $matches;
}, $text);
return $text;
}
]
(not tested)
Alternatively, you can register this hook in a plugin.
I made one small change to replace each $match with square brackets (which then render as round brackets) instead of the '⎣' and '⎦' characters:
So for anyone interested my final plugin in site/plugins/kirby-captions-brackets/index.php (which is working after some brief testing) is:
<?php
Kirby::plugin('alias/kirby-captions-brackets', [
'hooks' => [
'kirbytags:before' => function ($text, $data, $options) {
// KirbyTags have not been parsed
$text = preg_replace_callback('/\((?:[^()]+|(?R))*+\)/', function ($matches) {
// Loop through each tag and perform a second serach
foreach ($matches as $match) :
// First trim the () at the beginning and at the end
$match = substr($match , 1 , -1);
// Then look for () inside the string and replace them with another character
$match = str_replace('(', '[', $match);
$match = str_replace(')', ']', $match);
// Add back the two () at the beginning and the end
$match = "({$match})";
// Return the string
return $match;
endforeach;
# Return al the kirbytags
return $matches;
}, $text);
return $text;
}
]
]);