Abbreviations / glossary

We would like to use <abbr> for some words to manage some kind of glossary…
whats a good solution with kirby?
via kirbytags?
maybe some kind of automation via a seperated list and auto replace of text before rendering? (this would allow to catch everything on the website)
is it possible to inject something like this, right before the website is send to browser?

this thread from me is kind of related: Replace strings systemwide before rendering in the browser - #4 by demlak

We have a glossary here: Glossary | Kirby

The items in this glossary are used in the content via the glossary kirbytag: getkirby.com/guide.txt at aef9b24aadc8039a5a714326e48a8e5a5309dc83 · getkirby/getkirby.com · GitHub

When you hover over the items, the explanation is shown: Exploring the Starterkit | Kirby

Is that what you mean?

hey… thx for the quick reply…
yes this seems to be the behaviour i’m talking about…
i would like to replace by <attr> tag, because this tag has needed css (my theme uses uikit)

i would prefer an automatic solution… i found this:

maybe this could be a globaly solution? i have to test/check

It doesn’t really matter what you replace with or if you use Kirbytags or placeholder. After all, these are all just replacements.

My first test shows me, that the placeholders are not working in fluent blocks-texts… so like kirbytags :sleepy:

my prefered way would be a solution without adding brackets or kirbytag… just automatic-replacement all-over the site.

Well, of course you could create a regex pattern from an array of terms to do your replacement (using a kirbytext hook), but I wonder how performant that would be.

thx… kirbytexthook was a good tip… i’ll look into that.

so, i guess it is not possible to use placeholder function in a way without the curly brackets? i think, this would also fit the desired need

a simple return Str::template($text, $options, $start = '', $end = ''); seems to not work

I did not say it wasn’t possible, I’m just not sure how expensive such a regex pattern is with many terms (maybe it doesn’t even matter, but I don’t know):

	'hooks' => [
		'kirbytags:before' => function ($text) {
			return preg_replace_callback('!(term1|term2|term3)!siU', function (array $matches) {
				return '<abbr>' .  $matches[1] . '</abbr>';
			}, $text);
		}
	]

The regex pattern itself can be created from an array of terms.

thx a lot!

maybe i did understand something wrong… i just setup a new starter kit and tried placeholder example on a “note” page… so i gues this is the new editor… how to replace text in those text and quote (etc…) blocks? the example of the placeholder and/or your new snippet seem to work only for markdown blocks?

As a kirbytext hook, this only works with Kirbytext, that’s right.

ok… the obvious question: how to trigger also on other blocks? =)

This would work for blocks:

    <?php foreach( $page->text()->toBlocks() as $block) {
      $html = $block->toHtml(); 
      echo preg_replace_callback('!(term1|term2|term3)!siU', function (array $matches) use ($html) {
       	return '<abbr>' .  $matches[1] . '</abbr>';
      }, $html);

    } ?>

There should be a better way, though, maybe using map(), not sure.

i don’t understand where to put this… is this part of template? we were talking about the placeholder-plugin as a global option?!? sorry, i am a little bit confused right now

Yes, this is not global but would go into a template. No idea regarding global replacement.

If you only need this for text blocks, you can do the manipulation in the text block snippet.

Note that kirbytext hooks are not truely global, but only happen for stuff that you output via the kirbytext() method, but not in a headline or so.

Another option I could think of would be a custom toBlocks() field method.

this sounds promising… but

Be aware that you cannot override these default field methods with any custom field method.
(Field methods | Kirby)

well… i tried it anyways… and this works (kind of) =)
(based on a copy of the toBlocks() field method from /kirby/config/methods.php)

use Kirby\Cms\Blocks;
use Kirby\Cms\Field;

'toBlocks' => function (Field $field) {
    try {
    
        $blocks = Blocks::factory(Blocks::parse($field->value()), [
            'parent' => $field->parent(),
        ]);
        $html = $blocks->filter('isHidden', false);
        echo preg_replace_callback('!(term1|term2|term3)!siU', function (array $matches) use ($html) {
            return '<abbr>' .  $matches[1] . '</abbr>';
        }, $html);
    } catch (Throwable $e) {
        if ($field->parent() === null) {
            $message = 'Invalid blocks data for "' . $field->key() . '" field';
        } else {
            $message = 'Invalid blocks data for "' . $field->key() . '" field on parent "' . $field->parent()->title() . '"';
        }

        throw new InvalidArgumentException($message);
    }
},

i also want to use kirbytags-hook, so i gues have to iterate over each block to filter out markdown block… because the blocks parser seem to call also kirbytags hook on markdown blocks. What do you think?

As suggested by @distantantnative, there is also another option:

Use the kirbytext hook only and overwrite the relevant block type snippets, outputting the respective field with ->kt()

I didn’t really mean to overwrite the toBlocks() method but rather use your own custom method. But that would mean that you would have to replace toBlocks() with your custom method in your templates.

i am undecided… all ideas have their disadvantages…
rewriting toBlocks() field-method allows to build a plugin that is usable on different setups without knowlegde about custom blocks-snippets, template, etc…

but there could be a custom blocks-snippet, that uses kt()

is there any reason, why the editor does not use kt() by default for all kind of default blocks but only for markdown-blocks?

I cannot really answer this question, but there might be cases where calling kt() might cause issues. After all, the writer field is not a textarea field and is not supposed to have markdown or kirbytext in it, but you could actually add Kirbytags and they would be parsed, which is probably not a good idea or could even lead to errors.

Therefor this is a path I personally wouldn’t choose.

Thx @texnixe, i learned much today - and again the reason is you =)

as far as i understand it correctly, there is no solution to globaly replace text… reason is, that there are several ways to get text onto the website…

  1. in a centralized way, it is possible to replace text that is displayd via kt() by using placeholder, kirbytags, smartypants, etc.
    but normaly not all text on a website is displayed via kt()

  2. in a centralized way, it is possible to replace text that is displayed via toBlocks() by adding kt() to block snippets, or by overriding the field method itself…
    but normaly not all text on a website is displayed via toBlocks()

  3. and then, there is the writer-field, which generates output that does not need to be parsed via kt() and is normaly echoed straight to the website. maybe it is possible to extend the writer-field… but this also means to put “hard-coded” text into the content files. unless writer-fields are not activly parsed through (for example) kt(), there is no solution for automated text-replace

how bad is the idea of hooking into echo (new Kirby)->render(); that is called in index.php? =)
And i gues, this is not possible via plugin?