Hello there,
i am struggling with turning a Plugin that finds a custom tag and its value in a Kirbytext-Block and replaces it with a matching structure field entry. Here is the plugin (from: Sidenotes / Marginnotes in Kirby - #6 by bruno)
'tags' => [
'sn' => [
'html' => function($tag) {
$sidenotes = $tag->parent()->sidenotes()->toStructure();
$return = '';
if ($sidenotes
&& $note = $sidenotes->nth($tag->value() - 1)) {
$text = $note->text()->kirbyText();
$text = preg_replace( '/^<[^>]+>|<\/[^>]+>$/', '', $text);
$return = '<label for="sn-' . $tag->value . '" class="sidenote-number"></label><input type="checkbox" id="sn-' . $tag->value . '" class="margin-toggle"/><span class="sidenote">' . $text . '</span>';
$return = $return;
}
return $return;
}
],
],
However, this plugin only works for a page with one text and one sidenote structure field.
I would like to use it also on a page that loads multiple texts with different structure fields connected. Thats why i need to turn this plugin into a snippet function that needs 2 parameters: the block to skim through and the connected structure field containing the sidenotes. But i have absolutely no idea how i would structure such a function. I have not been able to search for the tags within a given block. There must be some kind of loop available, that finds all tags containing (sn: xx) and checks them back with the given structure fieldโฆ
Not sure I really understand. but would it be enough to either use a combined value like
(sn: sidenotes1:5)
where the string before the colon denotes the name of the field and the number after the colon the entry number.
Or you introduce a second attribute
(sn: 5 field: sitesnotes1)
In both cases, adapt the plugin accordingly.
Eg. for the first example:
'tags' => [
'sn' => [
'html' => function($tag) {
$values = Str::split($tag->value(), ':');
$sidenotes = $tag->parent()->{$values[0]}()->toStructure();
$return = '';
if ($sidenotes->count()
&& $note = $sidenotes->nth($values[1] - 1)) {
$text = $note->text()->kirbyText();
$text = preg_replace( '/^<[^>]+>|<\/[^>]+>$/', '', $text);
$return = '<label for="sn-' . $values[1] . '" class="sidenote-number"></label><input type="checkbox" id="sn-' . $values[1] . '" class="margin-toggle"/><span class="sidenote">' . $text . '</span>';
$return = $return;
}
return $return;
}
],
],
Thanks @texnixe !!
The reason i wanted to build a function in a snippet is, that i have templates, that have only one text + sidenotes and i have templates that can contain multiple texts + sidenotes.
The plugin will work on all templates the same way and with your proposed solution, i would have to do a lot of redundant work on pages with only one text (sn: sidenotes1:1) (sn: sidenotes1:2).
I now use a function like this:
<?php
function sidenotes($block, $sidenotes) {
$sidenotes = $sidenotes->toStructure();
$block = preg_replace_callback('|\(sn:[1-9]\)|', function($sidenote) use ($sidenotes) {
$number = str_replace('(sn:', '', $sidenote[0]);
$number = str_replace(')', '', $number);
if ($sidenotes && $sidenotes->isNotEmpty() && $note = $sidenotes->nth($number - 1)) {
$text = $note->text()->kirbyText();
$text = preg_replace( '/^<[^>]+>|<\/[^>]+>$/', '', $text);
return '<label for="sn-' . $sidenote[0] . '" class="sidenote-number"></label><input type="checkbox" id="sn-' . $sidenote[0] . '" class="margin-toggle"/><span class="sidenote">' . $text . '</span>';
}
}, $block);
echo $block;
}
?>
and just call it like this:
<? sidenotes($block, $page->sidenotes()); ?>
might not be the most elegant solution, but it works for me (at the moment)
As always: Many thanks for the swift response.