Columns in Kirbytext
KirbyTags are really great for use cases like adding images or links, but they come to a limit if you want to nest KirbyTags or want to add more than just a single line of text.
One such use case is adding columns inside a textarea field. In this recipe, we show you how to solve such uses with KirbyTag Hooks. When we are ready, you can add columns like this:
We use a starting and an ending tag, and columns are separated by a ++++
separator. The number of columns is not limited. Just add more ++++
separators for more columns.
Note that this syntax is only one way of solving this and we stick with this for compatibility reasons. On this website, we often use custom HTML tags, for example an <info>
tag to create the markup for this info box.
Implementation
KirbyText has a feature called pre and post filters. Pre filters are applied to text before KirbyTags and Markdown is parsed. Post filters are applied afterwards.
The filter plugin
KirbyTag Hooks are callbacks, which can be added to the kirbytags:before
or kirbytags:after
keys. Those callbacks can receive multiple arguments, here we only need the first parameter $text
, which contains the raw text, which can be modified and must be returned.
Our final result looks like this:
You can simply put this code into /site/plugins/columns/index.php
and start using columns in your KirbyText fields. If you want to understand the details, continue reading.
The regular expression voodoo
As the first step to achieve the syntax for the columns, we need to fetch the columns tags:
Let's examine the regular expression:
The exclamation marks define the beginning and the end of the expression.
is
at the end makes sure the expression is case insensitive and the s
tells the expression to include new lines.
We could simplify the inner part like this:
The backslashes are there to escape the brackets usually used to group matches, which you can see here: (.*)
. This little thing translates to: "take everything between the opening columns tag and the closing columns tag and put it in a group".
The final expression contains a bit more complexity to make sure an editor can use either an ellipsis or three dots:
This is achieved with a simple "or" clause, which looks like this:
The \.{3}
translates into: "a dot which repeats three times". A dot is another magic character in regular expressions and therefore has to be escaped with the backslash again.
Finally our regular expression fetches what we want and passes the matches to the callback function.
The $matches
variable is an array with the following content:
- the entire match starting with the beginning columns tag and ending with the closing tag
- the first "or" group (… or ...)
- the content between the tags
- the second "or" group (… or ...)
Since arrays start their index at zero, we can get the content between the tags with $matches[2]
Splitting content into columns
Now that we got the content in between the tags, we can look for our separators and split the content into nice pieces for the columns.
Since we are regular expression experts now, the expression above isn't that complicated anymore. The only new things are \R
, which stands for any line break, and \s
, which stands for spaces. So the expression above translates to: "Split the content when there's a line break, followed by four plus signs, follwed by one or more spaces, followed by a line break again."
With this, we get a $columns
array with text separated into chunks for our columns.
Nested KirbyText
The column tags are only useful if an editor can use KirbyText and Markdown inside of them. To achieve this, we have to manually parse the content for each column as KirbyText.
We can achieve this by passing each column to the $kirby->kirbytext()
method ($this
in this context references the Kirby object).
The final HTML
We end up with an $html
array with entries for each column. The HTML for each column looks like this:
A simple implode function together with a wrapping div makes everything complete.
As a last step, we add configurable class names to the div tags, so that you can set different class names in your config.php
file, for example:
CSS
To make the columns display correctly as columns, we finally need some CSS, in this example, we use the flexbox model, but you can adapt the markup classes and the styles to fit your needs (use floats, inline-blocks, CSS Grid layout…)
Once you've added the code above to your CSS file for your site, you should be able to see your grid.