Way to Use Parenthesis inside Kirbytag?

Oh man, this thing is haunting me! I’ve played with about 2 gazillion regular expressions in order to find a stable way to get nested parenthesis working, but everyone had another weakness. I’ve not fully explored all options for escaping yet though, because it always felt unintuitive. But if you think it’s a good way, I’ll give it a try.


So wanting a way to escape parenthesis with a backslash, and not finding a solution for it that actually works, I went with this:


kirbytext::$pre[] = function($kirbytext, $value) {
    return str_replace('\(','[[',str_replace('\)',']]',$value));
kirbytext::$post[] = function($kirbytext, $value) {
    return str_replace(']]',')',str_replace('[[','(',$value));

I saved this in plugins and called it escape.php. It’s a little hacky, but what it does is takes your escaped parentheses and changes them to something kirbytext will leave alone, then after kirbytext processes it switches them to regular parentheses.

You can always change the [[ and ]] to something even less likely to show up in your content. The beauty of this approach is that the user doesn’t have to learn what the alternate character is. The user only needs to know that to escape something you put a backslash in front of it, which is something a lot of users will already know, and many people will use as their first approach when trying to figure out how to get it to work.

1 Like

I found a solution and made PR. Any reviewers?

1 Like

Another real live example is a “link”:
Parenthesis in a link produces a wrong link

@iamvdo It’s interesting to see that a lot of people want this fixed! Apart from the filter solution proposed by @fitzage, yours was the second PR which fixes this issue - I had seen a previous one, here…:

The last couple of paragraphs in the commit are in English, so you’ll be able to see what it’s all about!

Kind of related is the problem of multiple attributes:

As per the example in documentation:

(wikipedia: Germany text:Here is some text)

That is easy. Wikipedia => “Germany” and text => “Here is some text”

What if I wanted to have another case like
(at1:This attribute has:a code at2:and something test2:something)
and want at1=>This attribute has:a code at2:and something test2=>something

Perhaps it would be an idea to have (enforce?) a little more structure on the kirbytags with attributes. At least until separators can be escaped.

If I do it in a panel field I can use:

May be you can use this too.

The last way is not correct!

I have found that ONLY the URL (href) has to be coded following RFC 3986.

Therefore is should be coded like

(link: https://de.wikipedia.org/wiki/Angeln_%28Fischfang%29 text: Angeln_&#x28;Fischfang&#x29; popup: yes)

which reders to

<a href="https://de.wikipedia.org/wiki/Angeln_%28Fischfang%29" rel="noopener noreferrer" target="_blank">Angeln_&#x28;Fischfang&#x29;</a>

Good luck!

Hi all

this work just fine with my kirbytext tag:

$preHtml = '';
$htmlBefore = '';
$htmlAfter = '';

kirbytext::$tags['text'] = array(
  'attr' => array(
  'html' => function($tag) {

    $class = $tag->attr('class');
    $text = $tag->attr('text');

    $preHtml = '<p class="' . $class . '">' . $text . '</p>';

    $htmlBefore = str_replace('\(', '[[' ,str_replace('\)',']]',$preHtml));

    $htmlAfter = str_replace(']]', ')', str_replace('[[','(',$htmlBefore));

    return $htmlAfter;



Old Thread… but here is a solution.

use % + Hex number mentioned here: https://www.ascii.cl/htmlcodes.htm

(link: https://de.wikipedia.org/wiki/Hohler_Stein_%28Kallenhardt%29 text: Kulturhöhle Hohler Stein)

If you follow my links in my posts above, you will find more Information regarding Kirby…

how can one adapt this to kirby3?

I get

Fatal error: Uncaught Error: Class 'kirbytext' not found in /Users/Shared/www/kfw-csr-2018/site/plugins/escape/index.php:3 

Trying to get it to work with hooks now

You can use a kirbytags:before hook: https://getkirby.com/docs/reference/plugins/extensions/kirbytags#kirbytag-hooks

thanks, I got it to work with the hook mentioned by you, but the after was needed, otherwise the problem persists in my case

// config.php

    'hooks' => [
        'kirbytext:after' => function ($text) {
            $snippets = array(
                '[' => '(',
                ']' => ')',
              $keys     = array_keys($snippets);
              $values   = array_values($snippets);
              return str_replace($keys, $values, $text);

Since this is still not resolved (Kirby 3.2 at time of posting), for everybody who stumbles upon this forum post in the future.
What I did, because I need all three kinds of brackets:

// this hook is a must, because I need (), [], and {} brackets inside my custom tags

    'hooks' => [
        'kirbytags:before' => function ($text, array $data = [], array $options = []) {

                                        //  v  WTF?
            $text = preg_replace_callback('/\\\\\)/', function () {
              return "}>}";  // replace it with this for a moment
            }, $text);

            return $text;
        'kirbytags:after' => function ($text, array $data = [], array $options = []) {

            $text = preg_replace_callback('/}>}/', function () {
              return ")";  // final replacement
            }, $text);

            return $text;

You still need to escape all not final closing brackets like this \) – otherwise with just ) you’d unwantedly catch also the final closing brackets. (And hope you never have actually the temporary replacement string somewhere… :D)
Annoying, but works at least.


I don’t know much about the code/what you guys need (it’s nothing I need right now) but when I see this

                                        //  v  WTF?

in the code, you know it’s a serious matter lol.


:smile: Small explanation here:
I normally use tools like regex101 to test my regex before they go into production.
Somehow /\\\)/ does not catch \), even tho it should ("\" and “)” have to be escaped).
By adding another pair of back slashes it worked, thus resulting in this monstrously /\\\\\)/. Not sure what shenanigans are at work here.

1 Like

This worked for me, it’s just missing an opening [ at the start:

Kirby::plugin('my/brackets', [
    'hooks' => [ ...
1 Like

hmm, this just renders the temporary replacement for me (k 3.3.4):

You can now use parentheses inside Kirbytags (at least if you don’t run into edge cases when using regex stuff inside your tags), Kirby 3.4.x, not Kirby 2, of course.